/*************************************************************************** gbc_form_webpage.c (c) 2000-2013 BenoƮt Minisini This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ***************************************************************************/ #define __GBC_FORM_WEBPAGE_C #include #include #include #include #include #include #include #include #include "gb_common.h" #include "gb_error.h" #include "gb_limit.h" #include "gb_file.h" #include "gb_str.h" #include "gbc_compile.h" #include "gbc_chown.h" #include "gbc_form.h" /*#define DEBUG*/ enum { TYPE_CODE, TYPE_HTML, TYPE_COMMENT, TYPE_MARKUP, TYPE_ARG, TYPE_ROOT }; static const char *_start; static void print_quoted_string(const char *str, int len) { int i; char buf[8]; uchar c; if (len == 0) return; FORM_print_char('"'); for (i = 0; i < len; i++) { c = (uchar)str[i]; //if (c >= ' ' && c <= 126 && c != '\\' && c != '"') if (c >= ' ' && c != '\\' && c != '"') FORM_print_char(c); else { FORM_print_char('\\'); if (c == '\n') c = 'n'; else if (c == '\r') c = 'r'; else if (c == '\t') c = 't'; else if (!(c == '"' || c == '\\')) { snprintf(buf, sizeof(buf), "x%02X", c); FORM_print_len(buf, 3); continue; } FORM_print_char(c); } } FORM_print_char('"'); } static void print_lower_len(const char *str, int len) { int i; for (i = 0; i < len; i++) FORM_print_char(tolower(str[i])); } static void flush_html(const char *end) { if (_start == end) return; FORM_print_len("Print ", 6); if (end[-1] == '\n') { print_quoted_string(_start, end - _start - 1); FORM_print_char('\n'); } else { print_quoted_string(_start, end - _start); FORM_print_len(";\n", 2); } _start = end; } static bool check_contents(const char *str, int len) { if (len < 4) return FALSE; if (str[0] == '-' && str[1] == '-' && str[len - 1] == '-' && str[len - 2] == '-') return TRUE; else return FALSE; } static int print_code(const char *str, int len) { char c; const char *start = str; //fprintf(stderr, "'%.*s'\n", len, str); while (len > 0) { c = *str++; len--; if (c == '"') { while (len > 0) { c = *str++; len--; if (c == '"') break; if (c == '\\' && *str) { str++; len--; } } } else if (c == '%' && *str == '>') { len = str - start - 1; FORM_print_len(start, len); return len + 2; } } THROW("&1: syntax error in form file", JOB->form); } static void print_markup(const char *str, int len) { int l; char c; const char *p; bool comma; bool quote; bool end; if (len <= 0) return; p = str; while (len > 0) { c = *str++; len--; if (c == ' ') break; } l = str - p - (c == ' '); if (*p == '/') { end = TRUE; p++; l--; } else end = FALSE; if (l <= 0) THROW(E_SYNTAX); FORM_print_len(p, l); if (end) { FORM_print(".__RenderEnd()\n"); return; } FORM_print(".__Render("); if (len > 0) { FORM_print_char('['); comma = FALSE; while (len > 0) { while (len > 0 && *str == ' ') { str++; len--; } if (len == 0) break; p = str; while (len > 0) { c = *str++; len--; if (c == '=' || c == ' ') break; } if (comma) FORM_print(", "); FORM_print_char('"'); l = str - p - (c == '='); print_lower_len(p, l); FORM_print("\": "); comma = TRUE; if (len <= 0 || c == ' ') { FORM_print("True"); continue; } p = str; // attr=<% ... %> if (len >= 3 && *str == '<' && str[1] == '%' && str[2] == '=') { str += 3; len -= 3; FORM_print_char('('); l = print_code(str, len); FORM_print_char(')'); str += l; len -= l; //fprintf(stderr, "-> '%.*s'\n", len, str); continue; } else if (*str == '"') { str++; len--; quote = TRUE; } else { quote = FALSE; } while (len > 0) { c = *str++; len--; if (quote) { if (len > 0 && c == '\\') { str++; len--; } else if (c == '"') break; } else { if (c == ' ') break; } } if (!quote && str == p) FORM_print("True"); else { if (!quote) FORM_print_char('"'); FORM_print_len(p, str - p); if (!quote) FORM_print_char('"'); } } FORM_print_char(']'); } FORM_print(")\n"); } void FORM_webpage(char *source) { char type = TYPE_CODE; char c; const char *p; int line; char buf[8]; bool has_contents = FALSE; line = FORM_FIRST_LINE; FORM_print("Inherits WebPage\n\n"); FORM_print("Public Sub _Render(Optional (_Arg) As Collection = New Collection)\n\n"); p = source; __PRINT: _start = p; for(;;) { c = *p++; if (!c) { flush_html(p - 1); goto __END; } if (c == '<') { if (*p == '%') { flush_html(p - 1); if (p[1] == '/' && p[2] == '%' && p[3] == '>') { p += 4; type = TYPE_ROOT; } else { p++; type = TYPE_CODE; } goto __CODE; } else if (*p == '<') { flush_html(p - 1); p++; type = TYPE_MARKUP; goto __CODE; } } if (c == '\n') { line++; if ((p - _start) >= 256) flush_html(p); } } __CODE: FORM_print("#Line "); sprintf(buf, "%d", line); FORM_print(buf); FORM_print_char('\n'); if (type == TYPE_CODE) { if (*p == '=') { type = TYPE_HTML; p++; } else if (*p == '!') { type = TYPE_ARG; p++; } else if (*p == '-' && p[1] == '-') { type = TYPE_COMMENT; p += 2; } else type = TYPE_CODE; } else if (type == TYPE_ROOT) { FORM_print("Print Html$(Application.Root);\n"); goto __PRINT; } _start = p; __END_STRING: for(;;) { c = *p++; if (!c) goto __ERROR; if (c == '"') goto __STRING; if (c == '\n') { line++; continue; } if (c == '%' && *p == '>' && type != TYPE_MARKUP) { switch (type) { case TYPE_CODE: FORM_print_len(_start, p - _start - 1); FORM_print_char('\n'); break; case TYPE_HTML: if ((p - _start) == 1) { FORM_print("Print Html$(Application.Root);\n"); } else { FORM_print("Print Html$("); FORM_print_len(_start, p - _start - 1); FORM_print(");\n"); } break; case TYPE_ARG: FORM_print("Print _Arg!"); print_lower_len(_start, p - _start - 1); FORM_print(";\n"); break; case TYPE_COMMENT: default: break; } p++; if (*p == '\n') { line++; p++; } goto __PRINT; } else if (c == '>' && *p == '>' && type == TYPE_MARKUP) { if (check_contents(_start, p - _start - 1)) { if (has_contents) THROW("Contents already declared"); has_contents = TRUE; FORM_print("\nEnd\n\n"); FORM_print("Public Sub _RenderEnd()\n\n"); } else { print_markup(_start, p - _start - 1); FORM_print_char('\n'); } p++; if (*p == '\n') { line++; p++; } goto __PRINT; } } __STRING: for(;;) { c = *p++; if (!c) goto __ERROR; if (c == '"') goto __END_STRING; if (c == '\\' && *p) p++; } __END: FORM_print("\nEnd\n\n"); return; __ERROR: THROW("&1: syntax error in form file", JOB->form); }