log.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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. void logit(struct session *ses, char *txt, FILE *file, int flags)
  26. {
  27. char out[BUFFER_SIZE];
  28. push_call("logit(%p,%p,%p,%d)",ses,txt,file,flags);
  29. if (HAS_BIT(ses->logmode, LOG_FLAG_PLAIN))
  30. {
  31. strip_vt102_codes(txt, out);
  32. }
  33. else if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
  34. {
  35. vt102_to_html(ses, txt, out);
  36. }
  37. else
  38. {
  39. strcpy(out, txt);
  40. }
  41. if (HAS_BIT(flags, LOG_FLAG_LINEFEED))
  42. {
  43. strcat(out, "\n");
  44. }
  45. fputs(out, file);
  46. fflush(file);
  47. pop_call();
  48. return;
  49. }
  50. void loginit(struct session *ses, FILE *file, int flags)
  51. {
  52. push_call("loginit(%p,%p,%d)",ses,file,flags);
  53. if (HAS_BIT(flags, LOG_FLAG_APPEND))
  54. {
  55. if (HAS_BIT(flags, LOG_FLAG_HTML))
  56. {
  57. fseek(file, 0, SEEK_END);
  58. if (ftell(file) == 0)
  59. {
  60. write_html_header(ses, file);
  61. }
  62. }
  63. }
  64. else if (HAS_BIT(flags, LOG_FLAG_OVERWRITE) && HAS_BIT(flags, LOG_FLAG_HTML))
  65. {
  66. if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
  67. {
  68. write_html_header(ses, file);
  69. }
  70. }
  71. pop_call();
  72. return;
  73. }
  74. DO_COMMAND(do_log)
  75. {
  76. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  77. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  78. arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN|SUB_ESC);
  79. if (*arg1 == 0)
  80. {
  81. show_error(ses, LIST_COMMAND, "#SYNTAX: #LOG {APPEND|OVERWRITE|OFF} {<FILENAME>}");
  82. }
  83. else if (is_abbrev(arg1, "APPEND") && *arg2 != 0)
  84. {
  85. if (ses->logfile)
  86. {
  87. fclose(ses->logfile);
  88. }
  89. if ((ses->logfile = fopen(arg2, "a")))
  90. {
  91. SET_BIT(ses->logmode, LOG_FLAG_APPEND);
  92. loginit(ses, ses->logfile, ses->logmode);
  93. show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", arg2, ftell(ses->logfile));
  94. }
  95. else
  96. {
  97. show_error(ses, LIST_COMMAND, "#ERROR: #LOG {%s} {%s} - COULDN'T OPEN FILE.", arg1, arg2);
  98. }
  99. }
  100. else if (is_abbrev(arg1, "OVERWRITE") && *arg2)
  101. {
  102. if (ses->logfile)
  103. {
  104. fclose(ses->logfile);
  105. }
  106. if ((ses->logfile = fopen(arg2, "w")))
  107. {
  108. SET_BIT(ses->logmode, LOG_FLAG_OVERWRITE);
  109. loginit(ses, ses->logfile, ses->logmode);
  110. show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s'", arg2);
  111. }
  112. else
  113. {
  114. show_error(ses, LIST_COMMAND, "#ERROR: #LOG {%s} {%s} - COULDN'T OPEN FILE.", arg1, arg2);
  115. }
  116. }
  117. else if (is_abbrev(arg1, "OFF"))
  118. {
  119. if (ses->logfile)
  120. {
  121. DEL_BIT(ses->logmode, LOG_FLAG_APPEND|LOG_FLAG_OVERWRITE);
  122. fclose(ses->logfile);
  123. ses->logfile = NULL;
  124. show_message(ses, LIST_COMMAND, "#LOG: LOGGING TURNED OFF.");
  125. }
  126. else
  127. {
  128. show_message(ses, LIST_COMMAND, "#LOG: LOGGING ALREADY TURNED OFF.");
  129. }
  130. }
  131. else
  132. {
  133. show_error(ses, LIST_COMMAND, "#SYNTAX: #LOG {APPEND|OVERWRITE|OFF} {<FILENAME>}");
  134. }
  135. return ses;
  136. }
  137. void write_html_header(struct session *ses, FILE *fp)
  138. {
  139. char header[BUFFER_SIZE];
  140. sprintf(header, "<html>\n"
  141. "<head>\n"
  142. "<meta http-equiv='content-type' content='text/html; charset=%s'>\n"
  143. "<meta name='viewport' content='width=device-width, initial-scale=1.0'>\n"
  144. "<meta name='description' content='Generated by TinTin++ "CLIENT_VERSION" - http://tintin.sourceforge.net'>\n"
  145. "<style type='text/css'>\n"
  146. "body {font-family:Consolas;font-size:12pt;}\n"
  147. "a {text-decoration:none;}\n"
  148. "a:link {color:#06b;}\n"
  149. "a:visited {color:#6b0;}\n"
  150. "a:hover {text-decoration:underline;}\n"
  151. "a:active {color:#b06;}\n"
  152. ".d30{ color: #000; } .l30{ color: #555; } .b40{ background-color: #000; } .b50{ background-color: #555 }\n"
  153. ".d31{ color: #B00; } .l31{ color: #F55; } .b41{ background-color: #B00; } .b51{ background-color: #F55 }\n"
  154. ".d32{ color: #0B0; } .l32{ color: #5F5; } .b42{ background-color: #0B0; } .b52{ background-color: #5F5 }\n"
  155. ".d33{ color: #BB0; } .l33{ color: #FF5; } .b43{ background-color: #BB0; } .b53{ background-color: #FF5 }\n"
  156. ".d34{ color: #00B; } .l34{ color: #55F; } .b44{ background-color: #00B; } .b54{ background-color: #55F }\n"
  157. ".d35{ color: #B0B; } .l35{ color: #F5F; } .b45{ background-color: #B0B; } .b55{ background-color: #F5F }\n"
  158. ".d36{ color: #0BB; } .l36{ color: #5FF; } .b46{ background-color: #0BB; } .b56{ background-color: #5FF }\n"
  159. ".d37{ color: #BBB; } .l37{ color: #FFF; } .b47{ background-color: #BBB; } .b57{ background-color: #FFF }\n"
  160. ".d38{ color: #FFF; } .l38{ color: #FFF; } .b48{ background-color: #000; } .b58{ background-color: #000 }\n"
  161. ".d39{ color: #FFF; } .l39{ color: #FFF; } .b49{ background-color: #000; } .b59{ background-color: #000 }\n"
  162. "</style>\n"
  163. "<body bgcolor='#000000'>\n"
  164. "</head>\n"
  165. "<pre>\n"
  166. "<span class='b49'><span class='d39'>\n",
  167. HAS_BIT(gtd->ses->charset, CHARSET_FLAG_UTF8) ? "utf-8" :
  168. HAS_BIT(ses->charset, CHARSET_FLAG_BIG5) ? "big5" :
  169. HAS_BIT(ses->charset, CHARSET_FLAG_GBK1) ? "gb18030" : "iso-8859-1");
  170. fputs(header, fp);
  171. }
  172. void vt102_to_html(struct session *ses, char *txt, char *out)
  173. {
  174. char tmp[BUFFER_SIZE], *pti, *pto;
  175. char xtc[] = { '0', '6', '8', 'B', 'D', 'F' };
  176. int vtc, fgc, bgc, cnt;
  177. int rgb[6] = { 0, 0, 0, 0, 0, 0 };
  178. vtc = ses->vtc;
  179. fgc = ses->fgc;
  180. bgc = ses->bgc;
  181. pti = txt;
  182. pto = out;
  183. while (*pti)
  184. {
  185. while (skip_vt102_codes_non_graph(pti))
  186. {
  187. pti += skip_vt102_codes_non_graph(pti);
  188. }
  189. switch (*pti)
  190. {
  191. case 27:
  192. pti += 2;
  193. for (cnt = 0 ; pti[cnt] ; cnt++)
  194. {
  195. tmp[cnt] = pti[cnt];
  196. if (pti[cnt] == ';' || pti[cnt] == 'm')
  197. {
  198. tmp[cnt] = 0;
  199. cnt = -1;
  200. pti += 1 + strlen(tmp);
  201. if (HAS_BIT(vtc, COL_XTF_R))
  202. {
  203. fgc = URANGE(0, atoi(tmp), 255);
  204. DEL_BIT(vtc, COL_XTF_R);
  205. SET_BIT(vtc, COL_XTF);
  206. }
  207. else if (HAS_BIT(vtc, COL_XTB_R))
  208. {
  209. bgc = URANGE(0, atoi(tmp), 255);
  210. DEL_BIT(vtc, COL_XTB_R);
  211. SET_BIT(vtc, COL_XTB);
  212. }
  213. else if (HAS_BIT(vtc, COL_TCF_R))
  214. {
  215. if (rgb[0] == 256)
  216. {
  217. rgb[0] = URANGE(0, atoi(tmp), 255);
  218. }
  219. else if (rgb[1] == 256)
  220. {
  221. rgb[1] = URANGE(0, atoi(tmp), 255);
  222. }
  223. else if (rgb[2] == 256)
  224. {
  225. rgb[2] = URANGE(0, atoi(tmp), 255);
  226. fgc = rgb[0] * 256 * 256 + rgb[1] * 256 + rgb[2];
  227. DEL_BIT(vtc, COL_TCF_R);
  228. SET_BIT(vtc, COL_TCF);
  229. }
  230. }
  231. else if (HAS_BIT(vtc, COL_TCB_R))
  232. {
  233. if (rgb[3] == 256)
  234. {
  235. rgb[3] = URANGE(0, atoi(tmp), 255);
  236. }
  237. else if (rgb[4] == 256)
  238. {
  239. rgb[4] = URANGE(0, atoi(tmp), 255);
  240. }
  241. else if (rgb[5] == 256)
  242. {
  243. rgb[5] = URANGE(0, atoi(tmp), 255);
  244. bgc = rgb[3] * 256 * 256 + rgb[4] * 256 + rgb[5];
  245. DEL_BIT(vtc, COL_TCB_R);
  246. SET_BIT(vtc, COL_TCB);
  247. }
  248. }
  249. else
  250. {
  251. switch (atoi(tmp))
  252. {
  253. case 0:
  254. vtc = 0;
  255. fgc = 39;
  256. bgc = 49;
  257. break;
  258. case 1:
  259. SET_BIT(vtc, COL_BLD);
  260. break;
  261. case 2:
  262. if (HAS_BIT(vtc, COL_TCF_2))
  263. {
  264. DEL_BIT(vtc, COL_XTF_5|COL_TCF_2);
  265. SET_BIT(vtc, COL_TCF_R);
  266. rgb[0] = 256; rgb[1] = 256; rgb[2] = 256;
  267. }
  268. else if (HAS_BIT(vtc, COL_TCB_2))
  269. {
  270. DEL_BIT(vtc, COL_XTB_5|COL_TCF_2);
  271. SET_BIT(vtc, COL_TCB_R);
  272. rgb[3] = 256; rgb[4] = 256; rgb[5] = 256;
  273. }
  274. else
  275. {
  276. DEL_BIT(vtc, COL_BLD);
  277. }
  278. break;
  279. case 5:
  280. if (HAS_BIT(vtc, COL_XTF_5))
  281. {
  282. DEL_BIT(vtc, COL_XTF_5|COL_TCF_2);
  283. SET_BIT(vtc, COL_XTF_R);
  284. }
  285. else if (HAS_BIT(vtc, COL_XTB_5))
  286. {
  287. DEL_BIT(vtc, COL_XTB_5|COL_TCF_2);
  288. SET_BIT(vtc, COL_XTB_R);
  289. }
  290. break;
  291. case 7:
  292. SET_BIT(vtc, COL_REV);
  293. break;
  294. case 21:
  295. case 22:
  296. DEL_BIT(vtc, COL_BLD);
  297. break;
  298. case 27:
  299. DEL_BIT(vtc, COL_REV);
  300. break;
  301. case 38:
  302. SET_BIT(vtc, COL_XTF_5|COL_TCF_2);
  303. fgc = 38;
  304. break;
  305. case 48:
  306. SET_BIT(vtc, COL_XTB_5|COL_TCB_2);
  307. bgc = 48;
  308. break;
  309. default:
  310. switch (atoi(tmp) / 10)
  311. {
  312. case 3:
  313. case 9:
  314. DEL_BIT(vtc, COL_XTF|COL_TCF);
  315. break;
  316. case 4:
  317. case 10:
  318. DEL_BIT(vtc, COL_XTB|COL_TCB);
  319. break;
  320. }
  321. if (atoi(tmp) / 10 == 4)
  322. {
  323. bgc = atoi(tmp);
  324. }
  325. if (atoi(tmp) / 10 == 10)
  326. {
  327. bgc = atoi(tmp) - 50;
  328. }
  329. if (atoi(tmp) / 10 == 3)
  330. {
  331. fgc = atoi(tmp);
  332. }
  333. if (atoi(tmp) / 10 == 9)
  334. {
  335. SET_BIT(vtc, COL_BLD);
  336. fgc = atoi(tmp) - 60;
  337. }
  338. break;
  339. }
  340. }
  341. }
  342. if (pti[-1] == 'm')
  343. {
  344. break;
  345. }
  346. }
  347. if (!HAS_BIT(vtc, COL_REV) && HAS_BIT(ses->vtc, COL_REV))
  348. {
  349. cnt = fgc;
  350. fgc = ses->fgc = bgc - 10;
  351. bgc = ses->bgc = cnt + 10;
  352. }
  353. if (bgc != ses->bgc || fgc != ses->fgc || vtc != ses->vtc)
  354. {
  355. sprintf(pto, "</span>");
  356. pto += strlen(pto);
  357. if (bgc != ses->bgc)
  358. {
  359. if (HAS_BIT(vtc, COL_XTB))
  360. {
  361. if (bgc < 8)
  362. {
  363. sprintf(pto, "</span><span class='b%d'>", 40+bgc);
  364. }
  365. else if (bgc < 16)
  366. {
  367. sprintf(pto, "</span><span class='b%d'>", 50+bgc-8);
  368. }
  369. else if (bgc < 232)
  370. {
  371. sprintf(pto, "</span><span style='background-color: #%c%c%c;'>", xtc[(bgc-16) / 36], xtc[(bgc-16) % 36 / 6], xtc[(bgc-16) % 6]);
  372. }
  373. else
  374. {
  375. sprintf(pto, "</span><span style='background-color: rgb(%d,%d,%d);'>", (bgc-232) * 10 + 8, (bgc-232) * 10 + 8,(bgc-232) * 10 + 8);
  376. }
  377. }
  378. else if (HAS_BIT(vtc, COL_TCB))
  379. {
  380. sprintf(pto, "</span><span style='background-color: rgb(%d,%d,%d);'>", rgb[3], rgb[4], rgb[5]);
  381. }
  382. else
  383. {
  384. sprintf(pto, "</span><span class='b%d'>", bgc);
  385. }
  386. pto += strlen(pto);
  387. }
  388. if (HAS_BIT(vtc, COL_XTF))
  389. {
  390. if (fgc < 8)
  391. {
  392. sprintf(pto, "<span class='d%d'>", 30+fgc);
  393. }
  394. else if (fgc < 16)
  395. {
  396. sprintf(pto, "<span class='l%d'>", 30+fgc-8);
  397. }
  398. else if (fgc < 232)
  399. {
  400. sprintf(pto, "<span style='color: #%c%c%c;'>", xtc[(fgc-16) / 36], xtc[(fgc-16) % 36 / 6], xtc[(fgc-16) % 6]);
  401. }
  402. else
  403. {
  404. sprintf(pto, "<span style='color: rgb(%d,%d,%d);'>", (fgc-232) * 10 + 8, (fgc-232) * 10 + 8,(fgc-232) * 10 + 8);
  405. }
  406. }
  407. else if (HAS_BIT(vtc, COL_TCF))
  408. {
  409. sprintf(pto, "<span style='color: rgb(%d,%d,%d);'>", fgc / 256 / 256, fgc / 256 % 256, fgc % 256);
  410. }
  411. else
  412. {
  413. if (HAS_BIT(vtc, COL_BLD))
  414. {
  415. sprintf(pto, "<span class='l%d'>", fgc);
  416. }
  417. else
  418. {
  419. sprintf(pto, "<span class='d%d'>", fgc);
  420. }
  421. }
  422. pto += strlen(pto);
  423. }
  424. if (HAS_BIT(vtc, COL_REV) && !HAS_BIT(ses->vtc, COL_REV))
  425. {
  426. cnt = fgc;
  427. fgc = ses->fgc = bgc - 10;
  428. bgc = ses->bgc = cnt + 10;
  429. }
  430. ses->vtc = vtc;
  431. ses->fgc = fgc;
  432. ses->bgc = bgc;
  433. break;
  434. case 6:
  435. *pto++ = '&';
  436. pti++;
  437. break;
  438. case 28:
  439. *pto++ = '<';
  440. pti++;
  441. break;
  442. case 30:
  443. *pto++ = '>';
  444. pti++;
  445. break;
  446. case '>':
  447. sprintf(pto, "&gt;");
  448. pto += strlen(pto);
  449. pti++;
  450. break;
  451. case '<':
  452. sprintf(pto, "&lt;");
  453. pto += strlen(pto);
  454. pti++;
  455. break;
  456. case '"':
  457. sprintf(pto, "&quot;");
  458. pto += strlen(pto);
  459. pti++;
  460. break;
  461. case '&':
  462. sprintf(pto, "&amp;");
  463. pto += strlen(pto);
  464. pti++;
  465. break;
  466. case '$':
  467. sprintf(pto, "&dollar;");
  468. pto += strlen(pto);
  469. pti++;
  470. break;
  471. case '\\':
  472. sprintf(pto, "&bsol;");
  473. pto += strlen(pto);
  474. pti++;
  475. break;
  476. case 0:
  477. break;
  478. default:
  479. *pto++ = *pti++;
  480. break;
  481. }
  482. }
  483. *pto = 0;
  484. }