log.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2020 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  18. ******************************************************************************/
  19. /******************************************************************************
  20. * T I N T I N + + *
  21. * *
  22. * coded by Igor van den Hoven 2004 *
  23. ******************************************************************************/
  24. #include "tintin.h"
  25. #define DO_LOG(log) void log (struct session *ses, char *arg, char *arg1, char *arg2)
  26. DO_LOG(log_append);
  27. DO_LOG(log_info);
  28. DO_LOG(log_make);
  29. DO_LOG(log_move);
  30. DO_LOG(log_overwrite);
  31. DO_LOG(log_off);
  32. DO_LOG(log_remove);
  33. DO_LOG(log_timestamp);
  34. typedef void LOG (struct session *ses, char *arg, char *arg1, char *arg2);
  35. struct log_type
  36. {
  37. char * name;
  38. LOG * fun;
  39. char * desc;
  40. };
  41. struct log_type log_table[] =
  42. {
  43. { "APPEND", log_append, "Start logging, appending to given file." },
  44. { "INFO", log_info, "Some logging related info." },
  45. { "MAKE", log_make, "Make the given directory." },
  46. { "MOVE", log_move, "Move the given file." },
  47. { "OFF", log_off, "Stop logging." },
  48. { "OVERWRITE", log_overwrite, "Start logging, overwriting the given file." },
  49. { "REMOVE", log_remove, "Remove the given file or directory." },
  50. { "TIMESTAMP", log_timestamp, "Timestamp prepended to each log line." },
  51. { "", NULL, "" }
  52. };
  53. DO_COMMAND(do_log)
  54. {
  55. int cnt;
  56. push_call("do_log(%p,%p)",ses,arg);
  57. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  58. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN|SUB_ESC);
  59. if (*arg1 == 0)
  60. {
  61. info:
  62. tintin_header(ses, 80, " LOG OPTIONS ");
  63. for (cnt = 0 ; *log_table[cnt].fun != NULL ; cnt++)
  64. {
  65. if (*log_table[cnt].desc)
  66. {
  67. tintin_printf2(ses, " [%-13s] %s", log_table[cnt].name, log_table[cnt].desc);
  68. }
  69. }
  70. pop_call();
  71. return ses;
  72. }
  73. else
  74. {
  75. for (cnt = 0 ; *log_table[cnt].name ; cnt++)
  76. {
  77. if (is_abbrev(arg1, log_table[cnt].name))
  78. {
  79. break;
  80. }
  81. }
  82. if (*log_table[cnt].name == 0)
  83. {
  84. goto info;
  85. }
  86. else
  87. {
  88. log_table[cnt].fun(ses, arg, arg1, arg2);
  89. }
  90. }
  91. pop_call();
  92. return ses;
  93. }
  94. DO_LOG(log_append)
  95. {
  96. if (ses->log->file)
  97. {
  98. fclose(ses->log->file);
  99. }
  100. if ((ses->log->file = fopen(arg2, "a")))
  101. {
  102. SET_BIT(ses->log->mode, LOG_FLAG_APPEND);
  103. RESTRING(ses->log->name, arg2);
  104. logheader(ses, ses->log->file, ses->log->mode);
  105. show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", arg2, ftell(ses->log->file));
  106. }
  107. else
  108. {
  109. show_error(ses, LIST_COMMAND, "#ERROR: #LOG {%s} {%s}: COULDN'T OPEN FILE.", arg1, arg2);
  110. }
  111. }
  112. DO_LOG(log_info)
  113. {
  114. tintin_printf2(ses, "#LOG INFO: FILE = %s", ses->log->file ? ses->log->name : "");
  115. tintin_printf2(ses, "#LOG INFO: LEVEL = %s", HAS_BIT(ses->log->mode, LOG_FLAG_LOW) ? "LOW" : "HIGH");
  116. tintin_printf2(ses, "#LOG INFO: MODE = %s", HAS_BIT(ses->log->mode, LOG_FLAG_HTML) ? "HTML" : HAS_BIT(ses->log->mode, LOG_FLAG_PLAIN) ? "PLAIN" : HAS_BIT(ses->log->mode, LOG_FLAG_RAW) ? "RAW" : "UNSET");
  117. tintin_printf2(ses, "#LOG INFO: LINE = %s", ses->log->line_file ? ses->log->line_name : "");
  118. tintin_printf2(ses, "#LOG INFO: NEXT = %s", ses->log->next_file ? ses->log->next_name : "");
  119. }
  120. DO_LOG(log_make)
  121. {
  122. if (mkdir(arg2, 0755))
  123. {
  124. if (errno != EEXIST)
  125. {
  126. show_error(ses, LIST_COMMAND, "#ERROR: #LOG MAKE: FAILED TO CREATE DIRECTORY {%s} (%s).", arg2, strerror(errno));
  127. }
  128. else
  129. {
  130. show_message(ses, LIST_COMMAND, "#LOG MAKE: DIRECTORY {%s} ALREADY EXISTS.", arg2);
  131. }
  132. }
  133. else
  134. {
  135. show_message(ses, LIST_COMMAND, "#LOG MAKE: CREATED DIRECTORY {%s}.", arg2);
  136. }
  137. }
  138. DO_LOG(log_move)
  139. {
  140. char *arg3;
  141. int result;
  142. arg3 = str_alloc_stack(0);
  143. arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN);
  144. result = rename(arg2, arg3);
  145. if (result == 0)
  146. {
  147. show_message(ses, LIST_COMMAND, "#LOG MOVE: FILE {%s} MOVED TO {%s}.", arg2, arg3);
  148. }
  149. else
  150. {
  151. show_error(ses, LIST_COMMAND, "#LOG MOVE: COULDN'T MOVE FILE {%s} TO {%s}.", arg2, arg3);
  152. }
  153. }
  154. DO_LOG(log_overwrite)
  155. {
  156. if (ses->log->file)
  157. {
  158. fclose(ses->log->file);
  159. }
  160. if ((ses->log->file = fopen(arg2, "w")))
  161. {
  162. SET_BIT(ses->log->mode, LOG_FLAG_OVERWRITE);
  163. RESTRING(ses->log->name, arg2);
  164. logheader(ses, ses->log->file, ses->log->mode);
  165. show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO {%s}", arg2);
  166. }
  167. else
  168. {
  169. show_error(ses, LIST_COMMAND, "#ERROR: #LOG {%s} {%s}: COULDN'T OPEN FILE.", arg1, arg2);
  170. }
  171. }
  172. DO_LOG(log_off)
  173. {
  174. if (ses->log->file)
  175. {
  176. DEL_BIT(ses->log->mode, LOG_FLAG_APPEND|LOG_FLAG_OVERWRITE);
  177. fclose(ses->log->file);
  178. ses->log->file = NULL;
  179. show_message(ses, LIST_COMMAND, "#LOG {OFF}: LOGGING TURNED OFF.");
  180. }
  181. else
  182. {
  183. show_message(ses, LIST_COMMAND, "#LOG: LOGGING ALREADY TURNED OFF.");
  184. }
  185. }
  186. DO_LOG(log_remove)
  187. {
  188. int result = remove(arg2);
  189. if (result == 0)
  190. {
  191. show_message(ses, LIST_COMMAND, "#LOG REMOVE: FILE {%s} REMOVED.", arg2);
  192. }
  193. else
  194. {
  195. show_error(ses, LIST_COMMAND, "#LOG REMOVE: COULDN'T REMOVE FILE {%s}.", arg2);
  196. }
  197. }
  198. DO_LOG(log_timestamp)
  199. {
  200. RESTRING(ses->log->stamp_strf, arg2);
  201. ses->log->stamp_time = 0;
  202. show_message(ses, LIST_COMMAND, "#LOG TIMESTAMP: FORMAT SET TO {%s}.", arg2);
  203. }
  204. void init_log(struct session *ses)
  205. {
  206. ses->log->name = strdup("");
  207. ses->log->next_name = strdup("");
  208. ses->log->line_name = strdup("");
  209. ses->log->stamp_strf = strdup("");
  210. }
  211. void free_log(struct session *ses)
  212. {
  213. free(ses->log->name);
  214. free(ses->log->next_name);
  215. free(ses->log->line_name);
  216. free(ses->log->stamp_strf);
  217. free(ses->log);
  218. }
  219. void logit(struct session *ses, char *txt, FILE *file, int flags)
  220. {
  221. char out[BUFFER_SIZE];
  222. push_call("logit(%p,%p,%p,%d)",ses,txt,file,flags);
  223. if (*ses->log->stamp_strf && (HAS_BIT(ses->log->mode, LOG_FLAG_STAMP) || file == ses->log->file))
  224. {
  225. if (ses->log->stamp_time != gtd->time)
  226. {
  227. struct tm timeval_tm = *localtime(&gtd->time);
  228. ses->log->stamp_time = gtd->time;
  229. substitute(ses, ses->log->stamp_strf, out, SUB_COL|SUB_ESC|SUB_VAR|SUB_FUN);
  230. strftime(ses->log->stamp_text, 99, out, &timeval_tm);
  231. }
  232. fputs(ses->log->stamp_text, file);
  233. }
  234. if (HAS_BIT(ses->log->mode, LOG_FLAG_PLAIN) || HAS_BIT(flags, LOG_FLAG_PLAIN))
  235. {
  236. strip_vt102_codes(txt, out);
  237. }
  238. else if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
  239. {
  240. vt102_to_html(ses, txt, out);
  241. }
  242. else
  243. {
  244. strcpy(out, txt);
  245. }
  246. if (HAS_BIT(flags, LOG_FLAG_LINEFEED))
  247. {
  248. strcat(out, "\n");
  249. }
  250. fputs(out, file);
  251. fflush(file);
  252. pop_call();
  253. return;
  254. }
  255. void logheader(struct session *ses, FILE *file, int flags)
  256. {
  257. push_call("logheader(%p,%p,%d)",ses,file,flags);
  258. if (HAS_BIT(flags, LOG_FLAG_APPEND))
  259. {
  260. if (HAS_BIT(flags, LOG_FLAG_HTML))
  261. {
  262. fseek(file, 0, SEEK_END);
  263. if (ftell(file) == 0)
  264. {
  265. write_html_header(ses, file);
  266. }
  267. }
  268. }
  269. else if (HAS_BIT(flags, LOG_FLAG_OVERWRITE) && HAS_BIT(flags, LOG_FLAG_HTML))
  270. {
  271. if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
  272. {
  273. write_html_header(ses, file);
  274. }
  275. }
  276. pop_call();
  277. return;
  278. }
  279. char *get_charset_html(struct session *ses)
  280. {
  281. int index;
  282. for (index = 0 ; *charset_table[index].name ; index++)
  283. {
  284. if (ses->charset == charset_table[index].flags)
  285. {
  286. return charset_table[index].html;
  287. }
  288. }
  289. return "";
  290. }
  291. void write_html_header(struct session *ses, FILE *fp)
  292. {
  293. char header[BUFFER_SIZE];
  294. sprintf(header,
  295. "<!DOCTYPE html>\n"
  296. "<html>\n"
  297. "<head>\n"
  298. "<meta http-equiv='content-type' content='text/html; charset=%s'>\n"
  299. "<meta name='viewport' content='width=device-width, initial-scale=1.0'>\n"
  300. "<style type='text/css'>\n"
  301. "body {font-family:Consolas;font-size:12pt}\n"
  302. "a {text-decoration:none}\n"
  303. "a:link {color:#06b}\n"
  304. "a:visited {color:#6b0}\n"
  305. "a:hover {text-decoration:underline}\n"
  306. "a:active {color:#b06}\n"
  307. "</style>\n"
  308. "<body bgcolor='#000000'>\n"
  309. "</head>\n"
  310. "<pre>\n"
  311. "<span style='background-color:#000'><span style='color:#FFF'>\n",
  312. get_charset_html(ses));
  313. fputs(header, fp);
  314. }
  315. void vt102_to_html(struct session *ses, char *txt, char *out)
  316. {
  317. char tmp[BUFFER_SIZE], *pti, *pto;
  318. char xtc[6] = { '0', '6', '8', 'B', 'D', 'F' };
  319. char *ans[16] = { "000", "A00", "0A0", "AA0", "00A", "A0A", "0AA", "AAA", "555", "F55", "5F5", "FF5", "55F", "F5F", "5FF", "FFF" };
  320. int vtc, fgc, bgc, cnt;
  321. int rgb[6] = { 0, 0, 0, 0, 0, 0 };
  322. vtc = ses->vtc;
  323. fgc = ses->fgc;
  324. bgc = ses->bgc;
  325. pti = txt;
  326. pto = out;
  327. while (*pti)
  328. {
  329. while (skip_vt102_codes_non_graph(pti))
  330. {
  331. pti += skip_vt102_codes_non_graph(pti);
  332. }
  333. switch (*pti)
  334. {
  335. case 27:
  336. pti += 2;
  337. for (cnt = 0 ; pti[cnt] ; cnt++)
  338. {
  339. tmp[cnt] = pti[cnt];
  340. if (pti[cnt] == ';' || pti[cnt] == 'm')
  341. {
  342. tmp[cnt] = 0;
  343. cnt = -1;
  344. pti += 1 + strlen(tmp);
  345. if (HAS_BIT(vtc, COL_XTF_R))
  346. {
  347. fgc = URANGE(0, atoi(tmp), 255);
  348. DEL_BIT(vtc, COL_XTF_R);
  349. SET_BIT(vtc, COL_XTF);
  350. }
  351. else if (HAS_BIT(vtc, COL_XTB_R))
  352. {
  353. bgc = URANGE(0, atoi(tmp), 255);
  354. DEL_BIT(vtc, COL_XTB_R);
  355. SET_BIT(vtc, COL_XTB);
  356. }
  357. else if (HAS_BIT(vtc, COL_TCF_R))
  358. {
  359. if (rgb[0] == 256)
  360. {
  361. rgb[0] = URANGE(0, atoi(tmp), 255);
  362. }
  363. else if (rgb[1] == 256)
  364. {
  365. rgb[1] = URANGE(0, atoi(tmp), 255);
  366. }
  367. else if (rgb[2] == 256)
  368. {
  369. rgb[2] = URANGE(0, atoi(tmp), 255);
  370. fgc = rgb[0] * 256 * 256 + rgb[1] * 256 + rgb[2];
  371. DEL_BIT(vtc, COL_TCF_R);
  372. SET_BIT(vtc, COL_TCF);
  373. }
  374. }
  375. else if (HAS_BIT(vtc, COL_TCB_R))
  376. {
  377. if (rgb[3] == 256)
  378. {
  379. rgb[3] = URANGE(0, atoi(tmp), 255);
  380. }
  381. else if (rgb[4] == 256)
  382. {
  383. rgb[4] = URANGE(0, atoi(tmp), 255);
  384. }
  385. else if (rgb[5] == 256)
  386. {
  387. rgb[5] = URANGE(0, atoi(tmp), 255);
  388. bgc = rgb[3] * 256 * 256 + rgb[4] * 256 + rgb[5];
  389. DEL_BIT(vtc, COL_TCB_R);
  390. SET_BIT(vtc, COL_TCB);
  391. }
  392. }
  393. else
  394. {
  395. switch (atoi(tmp))
  396. {
  397. case 0:
  398. vtc = 0;
  399. fgc = 7;
  400. bgc = 0;
  401. break;
  402. case 1:
  403. SET_BIT(vtc, COL_BLD);
  404. break;
  405. case 2:
  406. if (HAS_BIT(vtc, COL_TCF_2))
  407. {
  408. DEL_BIT(vtc, COL_XTF_5|COL_TCF_2);
  409. SET_BIT(vtc, COL_TCF_R);
  410. rgb[0] = 256; rgb[1] = 256; rgb[2] = 256;
  411. }
  412. else if (HAS_BIT(vtc, COL_TCB_2))
  413. {
  414. DEL_BIT(vtc, COL_XTB_5|COL_TCF_2);
  415. SET_BIT(vtc, COL_TCB_R);
  416. rgb[3] = 256; rgb[4] = 256; rgb[5] = 256;
  417. }
  418. else
  419. {
  420. DEL_BIT(vtc, COL_BLD);
  421. }
  422. break;
  423. case 5:
  424. if (HAS_BIT(vtc, COL_XTF_5))
  425. {
  426. DEL_BIT(vtc, COL_XTF_5|COL_TCF_2);
  427. SET_BIT(vtc, COL_XTF_R);
  428. }
  429. else if (HAS_BIT(vtc, COL_XTB_5))
  430. {
  431. DEL_BIT(vtc, COL_XTB_5|COL_TCF_2);
  432. SET_BIT(vtc, COL_XTB_R);
  433. }
  434. break;
  435. case 7:
  436. SET_BIT(vtc, COL_REV);
  437. break;
  438. case 21:
  439. case 22:
  440. DEL_BIT(vtc, COL_BLD);
  441. break;
  442. case 27:
  443. DEL_BIT(vtc, COL_REV);
  444. break;
  445. case 38:
  446. case 39:
  447. SET_BIT(vtc, COL_XTF_5|COL_TCF_2);
  448. fgc = 7;
  449. break;
  450. case 48:
  451. case 49:
  452. SET_BIT(vtc, COL_XTB_5|COL_TCB_2);
  453. bgc = 0;
  454. break;
  455. default:
  456. switch (atoi(tmp) / 10)
  457. {
  458. case 3:
  459. case 9:
  460. DEL_BIT(vtc, COL_XTF|COL_TCF);
  461. break;
  462. case 4:
  463. case 10:
  464. DEL_BIT(vtc, COL_XTB|COL_TCB);
  465. break;
  466. }
  467. if (atoi(tmp) / 10 == 4)
  468. {
  469. bgc = atoi(tmp) % 10;
  470. }
  471. else if (atoi(tmp) / 10 == 10)
  472. {
  473. bgc = atoi(tmp) % 10;
  474. }
  475. else if (atoi(tmp) / 10 == 3)
  476. {
  477. fgc = atoi(tmp) % 10;
  478. }
  479. else if (atoi(tmp) / 10 == 9)
  480. {
  481. SET_BIT(vtc, COL_BLD);
  482. fgc = atoi(tmp) % 10;
  483. }
  484. break;
  485. }
  486. }
  487. }
  488. if (pti[-1] == 'm')
  489. {
  490. break;
  491. }
  492. }
  493. if (!HAS_BIT(vtc, COL_REV) && HAS_BIT(ses->vtc, COL_REV))
  494. {
  495. cnt = fgc;
  496. fgc = ses->fgc = bgc;
  497. bgc = ses->bgc = cnt;
  498. }
  499. if (bgc != ses->bgc || fgc != ses->fgc || vtc != ses->vtc)
  500. {
  501. sprintf(pto, "</span>");
  502. pto += strlen(pto);
  503. if (bgc != ses->bgc)
  504. {
  505. if (HAS_BIT(vtc, COL_XTB))
  506. {
  507. if (bgc < 16)
  508. {
  509. sprintf(pto, "</span><span style='background-color: #%s'>", ans[bgc]);
  510. }
  511. else if (bgc < 232)
  512. {
  513. sprintf(pto, "</span><span style='background-color: #%c%c%c'>", xtc[(bgc-16) / 36], xtc[(bgc-16) % 36 / 6], xtc[(bgc-16) % 6]);
  514. }
  515. else
  516. {
  517. sprintf(pto, "</span><span style='background-color: rgb(%d,%d,%d)'>", (bgc-232) * 10 + 8, (bgc-232) * 10 + 8, (bgc-232) * 10 + 8);
  518. }
  519. }
  520. else if (HAS_BIT(vtc, COL_TCB))
  521. {
  522. sprintf(pto, "</span><span style='background-color:#%02x%02x%02x'>", rgb[3], rgb[4], rgb[5]);
  523. }
  524. else
  525. {
  526. sprintf(pto, "</span><span style='background-color:#%s'>", ans[bgc]);
  527. }
  528. pto += strlen(pto);
  529. }
  530. if (HAS_BIT(vtc, COL_XTF))
  531. {
  532. if (fgc < 16)
  533. {
  534. sprintf(pto, "</span><span style='color:#%s'>", ans[fgc]);
  535. }
  536. else if (fgc < 232)
  537. {
  538. sprintf(pto, "<span style='color:#%c%c%c'>", xtc[(fgc-16) / 36], xtc[(fgc-16) % 36 / 6], xtc[(fgc-16) % 6]);
  539. }
  540. else
  541. {
  542. sprintf(pto, "<span style='color:rgb(%d,%d,%d)'>", (fgc-232) * 10 + 8, (fgc-232) * 10 + 8,(fgc-232) * 10 + 8);
  543. }
  544. }
  545. else if (HAS_BIT(vtc, COL_TCF))
  546. {
  547. sprintf(pto, "<span style='color:#%02x%02x%02x'>", rgb[0], rgb[1], rgb[2]);
  548. }
  549. else
  550. {
  551. if (HAS_BIT(vtc, COL_BLD))
  552. {
  553. sprintf(pto, "<span style='color:#%s'>", ans[fgc+8]);
  554. }
  555. else
  556. {
  557. sprintf(pto, "<span style='color:#%s'>", ans[fgc]);
  558. }
  559. }
  560. pto += strlen(pto);
  561. }
  562. if (HAS_BIT(vtc, COL_REV) && !HAS_BIT(ses->vtc, COL_REV))
  563. {
  564. cnt = fgc;
  565. fgc = ses->fgc = bgc;
  566. bgc = ses->bgc = cnt;
  567. }
  568. ses->vtc = vtc;
  569. ses->fgc = fgc;
  570. ses->bgc = bgc;
  571. break;
  572. case 6:
  573. *pto++ = '&';
  574. pti++;
  575. break;
  576. case 28:
  577. *pto++ = '<';
  578. pti++;
  579. break;
  580. case 30:
  581. *pto++ = '>';
  582. pti++;
  583. break;
  584. case '>':
  585. sprintf(pto, "&gt;");
  586. pto += strlen(pto);
  587. pti++;
  588. break;
  589. case '<':
  590. sprintf(pto, "&lt;");
  591. pto += strlen(pto);
  592. pti++;
  593. break;
  594. case '"':
  595. sprintf(pto, "&quot;");
  596. pto += strlen(pto);
  597. pti++;
  598. break;
  599. case '&':
  600. sprintf(pto, "&amp;");
  601. pto += strlen(pto);
  602. pti++;
  603. break;
  604. case '$':
  605. sprintf(pto, "&dollar;");
  606. pto += strlen(pto);
  607. pti++;
  608. break;
  609. case '\\':
  610. sprintf(pto, "&bsol;");
  611. pto += strlen(pto);
  612. pti++;
  613. break;
  614. case 0:
  615. break;
  616. default:
  617. *pto++ = *pti++;
  618. break;
  619. }
  620. }
  621. *pto = 0;
  622. }