log.c 13 KB

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