htmlout.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /** --- BEGIN COPYRIGHT BLOCK ---
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. --- END COPYRIGHT BLOCK --- */
  6. /*
  7. * htmlout.c -- routines to output HTML elements -- HTTP gateway
  8. */
  9. #include "dsgw.h"
  10. #include "dbtdsgw.h"
  11. #define DSGW_POSTEDVARARG_NAME "name"
  12. static char*
  13. dsgw_change( char *s, dsgwsubst *changes )
  14. {
  15. auto dsgwsubst *ch;
  16. if ( changes == NULL ) return s;
  17. for ( ch = changes; ch; ch = ch->dsgwsubst_next ) {
  18. if ( strstr( s, ch->dsgwsubst_from ) ) {
  19. break;
  20. }
  21. }
  22. if ( ch != NULL ) {
  23. auto char *cs = dsgw_ch_strdup( s );
  24. for ( ch = changes; ch; ch = ch->dsgwsubst_next ) {
  25. auto const size_t from_len = strlen( ch->dsgwsubst_from );
  26. auto const size_t to_len = strlen( ch->dsgwsubst_to );
  27. auto const long change_len = to_len - from_len;
  28. auto char *p;
  29. for ( p = cs; (p = strstr( p, ch->dsgwsubst_from )) != NULL; p += to_len ) {
  30. if ( change_len ) {
  31. if ( change_len > 0 ) { /* allocate more space: */
  32. auto const size_t offset = p - cs;
  33. cs = dsgw_ch_realloc( cs, strlen( cs ) + change_len + 1 );
  34. p = cs + offset;
  35. }
  36. memmove( p + to_len, p + from_len, strlen( p + from_len ) + 1 );
  37. }
  38. if ( to_len != 0 ) {
  39. memcpy( p, ch->dsgwsubst_to, to_len );
  40. }
  41. }
  42. }
  43. return cs;
  44. }
  45. return s;
  46. }
  47. void
  48. dsgw_HTML_emits( char *s )
  49. {
  50. auto char *sc = dsgw_change( s, gc->gc_changeHTML );
  51. dsgw_emits( sc );
  52. if ( sc != s ) free( sc );
  53. }
  54. void
  55. dsgw_html_begin( char *title, int titleinbody )
  56. {
  57. static int header_done = 0;
  58. if ( !header_done ) {
  59. dsgw_emits( "<HTML>" );
  60. dsgw_head_begin();
  61. dsgw_emits( "\n" );
  62. if ( title != NULL ) {
  63. dsgw_emitf( "<TITLE>%s</TITLE>\n", title );
  64. }
  65. dsgw_emitf( "</HEAD>\n<BODY %s>\n", dsgw_html_body_colors );
  66. } else {
  67. dsgw_emits( "\n<HR>\n" );
  68. }
  69. if (( title != NULL ) && ( header_done || titleinbody )) {
  70. dsgw_emitf( "<CENTER><TABLE BORDER=\"2\" CELLPADDING=\"10\" WIDTH=100%%>\n"
  71. "<TR><TD ALIGN=\"center\" WIDTH=\"100%%\">\n<FONT SIZE=\"+2\">"
  72. "<B>%s</B></FONT></TD></TR></TABLE></CENTER>\n<P>\n", title );
  73. }
  74. header_done = 1;
  75. }
  76. void
  77. dsgw_html_end()
  78. {
  79. dsgw_emits( "</BODY></HTML>\n" );
  80. /* make sure everything has been written to the server before we exit */
  81. fflush( stdout );
  82. fflush( stderr );
  83. }
  84. /*
  85. * output a hypertext reference/URL:
  86. * if "urlprefix" != NULL, it is prepended to "url" and "url" is hex-escaped.
  87. * if "urlprefix" == NULL, "url" is assumed to be already escaped as needed.
  88. *
  89. * if "value" != NULL, any occurrence of "--value--" in "url" is replaced by
  90. * a URL-escaped version of the actual value.
  91. * if "value" == NULL, no substitution is done.
  92. *
  93. * if "label" == NULL or is of zero length, the closing ">LABEL</A>" is omitted.
  94. */
  95. void
  96. dsgw_html_href( char *urlprefix, char *url, char *label, char *value,
  97. char *extra )
  98. {
  99. char *escaped_url, *tag = "--value--";
  100. char *newlabel = NULL;
  101. int freenewlabel;
  102. if ( urlprefix == NULL ) {
  103. dsgw_emits( "<A HREF=" );
  104. escaped_url = NULL;
  105. } else {
  106. dsgw_emitf( "<A HREF=%s", urlprefix );
  107. escaped_url = dsgw_ch_malloc( 3 * strlen( url ) + 1 );
  108. *escaped_url = '\0';
  109. dsgw_strcat_escaped( escaped_url, url );
  110. url = escaped_url;
  111. }
  112. if ( value != NULL ) {
  113. dsgw_substitute_and_output( url, tag, value, 1 );
  114. } else {
  115. dsgw_emits( url );
  116. }
  117. if ( extra != NULL ) {
  118. dsgw_emits( " " );
  119. if ( value != NULL ) {
  120. dsgw_substitute_and_output( extra, tag, value, 1 );
  121. } else {
  122. dsgw_emits( extra );
  123. }
  124. }
  125. newlabel = dsgw_strdup_with_entities( label, &freenewlabel );
  126. if ( newlabel != NULL && *newlabel != '\0' ) {
  127. dsgw_emitf( ">%s</A>\n", newlabel );
  128. if ( freenewlabel ) {
  129. free( newlabel );
  130. }
  131. } else {
  132. dsgw_emits( "></A>\n" );
  133. }
  134. if ( escaped_url != NULL ) {
  135. free( escaped_url );
  136. }
  137. }
  138. void
  139. dsgw_substitute_and_output( char *s, char *tag, char *value, int escape )
  140. {
  141. char *p, *escval;
  142. escval = NULL;
  143. while ( ( p = strstr( s, tag )) != NULL ) {
  144. if ( p > s ) {
  145. dsgw_emitn( stdout, s, p - s );
  146. }
  147. if ( escape ) {
  148. if ( escval == NULL ) {
  149. escval = dsgw_strdup_escaped( value );
  150. }
  151. dsgw_emits( escval );
  152. } else {
  153. dsgw_emits( value );
  154. }
  155. s = p + strlen( tag );
  156. }
  157. if ( escval != NULL ) {
  158. free( escval );
  159. }
  160. if ( *s != '\0' ) {
  161. dsgw_emits( s );
  162. }
  163. }
  164. char *
  165. dsgw_strdup_escaped( const char *s )
  166. {
  167. char *p;
  168. p = dsgw_ch_malloc( 3 * strlen( s ) + 1 );
  169. *p = '\0';
  170. dsgw_strcat_escaped( p, s );
  171. return( p );
  172. }
  173. /* this macro was copied from libldap/tmplout.c */
  174. #define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \
  175. ( c >= '@' && c <= 'Z' ) || \
  176. ( c == '_' ) || \
  177. ( c >= 'a' && c <= 'z' ))
  178. /* this function is copied from libldap/tmplout.c:strcat_escaped */
  179. void
  180. dsgw_strcat_escaped( char *s1, const char *s2 )
  181. {
  182. unsigned char *q;
  183. char *p, *hexdig = "0123456789ABCDEF";
  184. p = s1 + strlen( s1 );
  185. for ( q = (unsigned char *)s2; *q != '\0'; ++q ) {
  186. if ( HREF_CHAR_ACCEPTABLE( *q )) {
  187. *p++ = *q;
  188. } else {
  189. *p++ = '%';
  190. *p++ = hexdig[ 0x0F & ((*(unsigned char*)q) >> 4) ];
  191. *p++ = hexdig[ 0x0F & *q ];
  192. }
  193. }
  194. *p = '\0';
  195. }
  196. #define DSGW_MAX_ENTITY_LEN 6 /* &quot; */
  197. static char *specials = "&\"<>";
  198. static char *entities[] = { "&amp;", "&quot;", "&lt;", "&gt;" };
  199. static int entitylen[] = { 5, 6, 4, 4 };
  200. char *
  201. dsgw_strdup_with_entities( char *s, int *madecopyp )
  202. {
  203. /*
  204. * If the UTF8 string "s" contains any HTML special characters, make a
  205. * duplicate where the appropriate HTML "entities" have been substituted
  206. * for the special chars. For example, "<[email protected]>" will be translated
  207. * to "&lt;[email protected]&gt;".
  208. *
  209. * If "s" does not contain any special characters, it is returned and
  210. * *madecopyp is set to 0.
  211. * Otherwise a malloc'd string is returned and *madecopyp is set to 1.
  212. */
  213. int spcount, idx;
  214. char *p, *q, *r, *d;
  215. spcount = 0;
  216. for ( p = s; *p != '\0'; LDAP_UTF8INC( p )) {
  217. if ( ((*p) & 0x80) == 0 && strchr( specials, *p ) != NULL ) {
  218. ++spcount;
  219. }
  220. }
  221. if ( spcount == 0 ) {
  222. *madecopyp = 0;
  223. return( s );
  224. }
  225. d = r = dsgw_ch_malloc( strlen( s ) + 1 + spcount * DSGW_MAX_ENTITY_LEN );
  226. for ( p = s; *p != '\0'; LDAP_UTF8INC( p )) {
  227. if ( ((*p) & 0x80) == 0 && ( q = strchr( specials, *p )) != NULL ) {
  228. idx = ( q - specials );
  229. memcpy( r, entities[ idx ], entitylen[ idx ] );
  230. r += entitylen[ idx ];
  231. } else {
  232. r += LDAP_UTF8COPY( r, p );
  233. }
  234. }
  235. *r = '\0';
  236. *madecopyp = 1;
  237. return( d );
  238. }
  239. void
  240. dsgw_form_begin( const char* name, const char* format, ... )
  241. {
  242. dsgw_emits ("<FORM method=POST");
  243. if (name) {
  244. dsgw_emitf (" name=\"%s\"", name);
  245. }
  246. if (format) {
  247. va_list argl;
  248. va_start (argl, format);
  249. dsgw_emits (" ");
  250. dsgw_emitfv (format, argl);
  251. va_end (argl);
  252. }
  253. dsgw_emits (">");
  254. dsgw_emitf("<INPUT type=hidden name=context value=\"%s\">", context);
  255. dsgw_emitf ("<INPUT type=hidden name=charset value=\"%s\">",
  256. (gc->gc_charset && *(gc->gc_charset)) ? gc->gc_charset : ISO_8859_1_ENCODING );
  257. }
  258. void
  259. dsgw_emit_cgi_var( int argc, char **argv )
  260. {
  261. char *name, *postedvalue;
  262. if (( name = get_arg_by_name( DSGW_POSTEDVARARG_NAME, argc, argv ))
  263. == NULL ) {
  264. dsgw_emitf( XP_GetClientStr(DBT_missingS_1), DSGW_POSTEDVARARG_NAME );
  265. } else if (( postedvalue = dsgw_get_cgi_var( name, DSGW_CGIVAR_OPTIONAL ))
  266. != NULL ) {
  267. dsgw_emits( postedvalue );
  268. }
  269. }
  270. void
  271. dsgw_emit_button( int argc, char **argv, const char* format, ... )
  272. {
  273. auto char *name = get_arg_by_name( DSGW_ARG_BUTTON_NAME, argc, argv );
  274. auto char *label = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc, argv );
  275. if ( !label ) label = XP_GetClientStr( DBT_closeWindow_3 );
  276. dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\"", label );
  277. if ( name ) dsgw_emitf( " NAME=\"%s\"", name );
  278. if ( format ) {
  279. va_list argl;
  280. va_start( argl, format );
  281. dsgw_emits( " " );
  282. dsgw_emitfv( format, argl );
  283. va_end( argl );
  284. }
  285. dsgw_emits( ">" );
  286. }
  287. void
  288. dsgw_emit_alertForm ()
  289. {
  290. dsgw_form_begin ("alertForm", "action=\"%s\" target=alertWindow",
  291. DSGW_URLPREFIX_MAIN_HTTP "alert.html");
  292. dsgw_emitf ("<INPUT TYPE=hidden NAME=TITLE VALUE=\"%s\">", XP_GetClientStr(DBT_alertTitle_));
  293. dsgw_emits ("<INPUT TYPE=hidden NAME=MSG VALUE=\"\">"
  294. "</FORM>\n");
  295. }
  296. void
  297. dsgw_emit_confirmForm ()
  298. {
  299. dsgw_form_begin ("confirmForm", "action=\"%s\" target=confirmWindow",
  300. DSGW_URLPREFIX_MAIN_HTTP "confirm.html");
  301. dsgw_emitf ("<INPUT TYPE=hidden NAME=TITLE VALUE=\"%s\">", XP_GetClientStr(DBT_confirmTitle_));
  302. dsgw_emits ("<INPUT TYPE=hidden NAME=MSG VALUE=\"\">"
  303. "<INPUT TYPE=hidden NAME=YES VALUE=\"\">"
  304. "<INPUT TYPE=hidden NAME=NO VALUE=\"\">"
  305. "</FORM>\n");
  306. }
  307. static const char*
  308. defaultWindowOptions = "width=350,height=130,resizable";
  309. void
  310. dsgw_emit_alert (const char* frame, const char* windowOptions, const char* format, ...)
  311. {
  312. if (!windowOptions) windowOptions = defaultWindowOptions;
  313. dsgw_emits (" var aw = window.open(");
  314. dsgw_emits ("''");
  315. /* dsgw_quote_emits (QUOTATION_JAVASCRIPT, DSGW_URLPREFIX_MAIN_HTTP "emptyFrame.html"); */
  316. dsgw_emits ( ", 'alertWindow', ");
  317. dsgw_quote_emits (QUOTATION_JAVASCRIPT, windowOptions);
  318. dsgw_emits ( ");\n"
  319. " aw.focus();\n"
  320. " window."); /* Navigator 3 needs this */
  321. if (frame) dsgw_emitf ("%s.", frame);
  322. dsgw_emits ( "document.alertForm.MSG.value =");
  323. dsgw_quotation_begin (QUOTATION_JAVASCRIPT);
  324. if (format) {
  325. va_list argl;
  326. va_start (argl, format);
  327. dsgw_emitfv (format, argl);
  328. va_end (argl);
  329. }
  330. dsgw_quotation_end();
  331. dsgw_emits ( ";\n"
  332. " window.");
  333. if (frame) dsgw_emitf ("%s.", frame);
  334. dsgw_emits ("document.alertForm.submit();\n");
  335. }
  336. void
  337. dsgw_emit_confirm (const char* frame, const char* yes, const char* no,
  338. const char* windowOptions, int enquote, const char* format, ...)
  339. {
  340. if (!windowOptions) windowOptions = defaultWindowOptions;
  341. dsgw_emits (" cw = window.open ('', 'confirmWindow', ");
  342. dsgw_quote_emits (QUOTATION_JAVASCRIPT, windowOptions);
  343. dsgw_emits ( ");\n"
  344. " cw.focus();\n"
  345. " if (cw.opener == null) cw.opener = self;\n" /* Navigator 2 needs this */
  346. " window."); /* Navigator 3 needs this */
  347. if (frame) dsgw_emitf ("%s.", frame);
  348. dsgw_emits ( "document.confirmForm.MSG.value = ");
  349. if (enquote) dsgw_quotation_begin (QUOTATION_JAVASCRIPT);
  350. if (format) {
  351. va_list argl;
  352. va_start (argl, format);
  353. dsgw_emitfv (format, argl);
  354. va_end (argl);
  355. }
  356. if (enquote) dsgw_quotation_end();
  357. dsgw_emits ( ";\n");
  358. dsgw_emits (" window.");
  359. if (frame) dsgw_emitf ("%s.", frame);
  360. dsgw_emits ( "document.confirmForm.YES.value = ");
  361. dsgw_quote_emits (QUOTATION_JAVASCRIPT, yes ? yes : "");
  362. dsgw_emits ( ";\n");
  363. dsgw_emits (" window.");
  364. if (frame) dsgw_emitf ("%s.", frame);
  365. dsgw_emits ( "document.confirmForm.NO.value = ");
  366. dsgw_quote_emits (QUOTATION_JAVASCRIPT, no ? no : "");
  367. dsgw_emits ( ";\n");
  368. dsgw_emits (" window.");
  369. if (frame) dsgw_emitf ("%s.", frame);
  370. dsgw_emits ( "document.confirmForm.submit();\n");
  371. }