reg_html.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /***************************************************************************
  2. * reg_html.c
  3. *
  4. * Fri May 20 18:14:32 2005
  5. * Copyright 2005 User
  6. * Email
  7. ****************************************************************************/
  8. /*
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. #include "globals.h"
  24. void new_ext_html(char *ext, char *gisbase, char **html, int major, int minor,
  25. int revision)
  26. {
  27. int pos1, pos2, pos3;
  28. int start, end;
  29. int insert_here;
  30. char *first_char;
  31. char *last_char;
  32. char item[MAXSTR];
  33. int len;
  34. pos1 = find_pos("<b>Drivers sections:</b>", html, 0); /* first go to section on "Drivers" */
  35. if (pos1 < 0) {
  36. /* we have a new version of the HTML docs that does not have a "Drivers" section anymore */
  37. /* let's check for the special GEM comment */
  38. pos1 =
  39. find_pos
  40. ("<!-- GEM Extensions StartHTML. Do not delete or change this comment! -->",
  41. html, 0);
  42. if (pos1 < 0) {
  43. /* sorry, I can't handle these HTML docs */
  44. print_warning
  45. ("Unknown format of index.html. Unable to register HTML man pages.\n");
  46. return;
  47. }
  48. }
  49. pos2 = find_pos("<hr>", html, pos1); /* the horizontal ruler marks the end of the HTML text */
  50. if (find_pos("<h3>Installed extensions:</h3>", html, pos1) == -1) {
  51. /* Extensions section does not yet exist: create it now */
  52. insert_str("<h3>Installed extensions:</h3>\n", pos2, html);
  53. insert_str("<ul>\n", pos2 + 1, html);
  54. insert_str("</ul>\n", pos2 + 2, html);
  55. insert_str("<p>\n", pos2 + 3, html);
  56. }
  57. start = find_pos("<h3>Installed extensions:</h3>", html, pos1);
  58. end = find_pos("</ul>", html, start);
  59. insert_here = start + 2;
  60. /* check if this entry already exists and if so: bail out or overwrite, if force mode */
  61. sprintf(item, "\">%s", ext);
  62. pos3 = find_pos(item, html, insert_here);
  63. if (pos3 != -1) {
  64. /* exists: */
  65. print_warning("list item '%s' exists in index.html.\n", ext);
  66. if ((FORCE) && (UPGRADE)) {
  67. sprintf(item,
  68. "<li><a href=\"../extensions/%s/index.html\">%s (%i.%i.%i)</a>\n",
  69. ext, ext, major, minor, revision);
  70. strcpy(html[pos3], item);
  71. }
  72. return;
  73. }
  74. /* now go through all links in the Extensions section and insert this one in the right
  75. alphabetical position */
  76. pos3 = find_pos("<li><a href=", html, start);
  77. while ((pos3 != -1) && (pos3 < end)) {
  78. /* extract name of extension at this position */
  79. first_char = strrchr(html[pos3], '"');
  80. last_char = strrchr(html[pos3], '<');
  81. len = (last_char - first_char) / sizeof(char);
  82. strncpy(item, first_char + 2 * sizeof(char), len);
  83. item[len - 1] = '\0'; /* get rid of '<' */
  84. if (strcmp(ext, item) < 0) {
  85. insert_here = pos3;
  86. break; /* found our position: let's quit this! */
  87. }
  88. /* look for next item */
  89. start++;
  90. pos3 = find_pos("<li><a href=", html, start);
  91. }
  92. /* now insert new entry for this extension */
  93. sprintf(item,
  94. "<li><a href=\"../extensions/%s/index.html\">%s (%i.%i.%i)</a>\n",
  95. ext, ext, major, minor, revision);
  96. insert_str(item, insert_here, html);
  97. }
  98. void delete_ext_html(char *ext, char *gisbase, char **html)
  99. {
  100. int pos1, pos2, pos3;
  101. int start, end;
  102. char item[MAXSTR];
  103. int found;
  104. int i;
  105. pos1 = find_pos("<b>Drivers sections:</b>", html, 0); /* first go to section on "Drivers" */
  106. if (pos1 < 0) {
  107. /* we have a new version of the HTML docs that does not have a "Drivers" section anymore */
  108. /* let's check for the special GEM comment */
  109. pos1 =
  110. find_pos
  111. ("<!-- GEM Extensions StartHTML. Do not delete or change this comment! -->",
  112. html, 0);
  113. if (pos1 < 0) {
  114. /* sorry, I can't handle these HTML docs */
  115. print_warning
  116. ("Unknown format of index.html. Unable to de-register HTML man pages.\n");
  117. return;
  118. }
  119. }
  120. pos2 = find_pos("<hr>", html, pos1); /* the horizontal ruler marks the end of the HTML text */
  121. if (find_pos("<h3>Installed extensions:</h3>", html, pos1) == -1) {
  122. /* Extensions section does not exist: bail out! */
  123. print_warning("no extensions section found in index.html.\n");
  124. return;
  125. }
  126. start = find_pos("<h3>Installed extensions:</h3>", html, pos1);
  127. end = find_pos("</ul>", html, start);
  128. /* check if the entry exists and if so delete */
  129. found = 0;
  130. sprintf(item, "\">%s", ext);
  131. pos3 = find_pos(item, html, start);
  132. if (pos3 == -1) {
  133. /* does not exist: */
  134. print_warning("extension '%s' not listed in index.html.\n", ext);
  135. return;
  136. }
  137. /* delete item, if it was found in the extensions section */
  138. if (pos3 < end) {
  139. delete_str(pos3, html);
  140. }
  141. end--; /* end of extensions section is no one up! */
  142. /* if no more entries left in the extensions list: delete the entire section */
  143. pos3 = find_pos("<ul>", html, start);
  144. if ((pos3 != -1) && (end > pos3) && (end - pos3 < 2)) {
  145. for (i = 0; i < 4; i++) {
  146. delete_str(pos3 - 1, html);
  147. }
  148. }
  149. }
  150. void register_html(char *pkg_short_name, char *gisbase, int major, int minor,
  151. int revision)
  152. {
  153. char file[MAXSTR];
  154. char str[MAXSTR];
  155. char **line;
  156. int n_lines, i;
  157. FILE *f_in, *f_out;
  158. /* check if index.html exists and is readable */
  159. sprintf(file, "%s/docs/html/index.html", gisbase);
  160. f_in = fopen(file, "r");
  161. if (f_in == NULL) {
  162. if (errno == ENOENT) {
  163. /* file does not exist */
  164. return;
  165. }
  166. else {
  167. /* sth. strange happened */
  168. fclose(f_in);
  169. print_error(ERR_REGISTER_HTML, "checking for file '%s': %s\n",
  170. file, strerror(errno));
  171. }
  172. }
  173. /* create a temporary index.html copy for write access */
  174. /* TODO: Do not hardcode temp paths */
  175. strcpy(TMP_HTML, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_HTML is a global variable */
  176. mkstemp(TMP_HTML);
  177. f_out = fopen(TMP_HTML, "w+");
  178. if (f_out == NULL) {
  179. print_error(ERR_REGISTER_HTML,
  180. "could not create temp file '%s': %s\n \
  181. Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_HTML, strerror(errno));
  182. }
  183. atexit(&exit_db); /* now need to register an at exit func to remove tmpdb automatically! */
  184. /* everything fine: create a shell command to install HTML stuff */
  185. if (VERBOSE) {
  186. sprintf(str,
  187. "cp -vf %s %s/docs/html/index.html ; chmod -v a+r %s/docs/html/index.html ;",
  188. TMP_HTML, gisbase, gisbase);
  189. }
  190. else {
  191. sprintf(str,
  192. "cp -f %s %s/docs/html/index.html &>%s ; chmod a+r %s/docs/html/index.html &>%s ;",
  193. TMP_HTML, gisbase, TMP_NULL, gisbase, TMP_NULL);
  194. }
  195. strcpy(HTML_CMD, str);
  196. /* count number of lines in index.html */
  197. n_lines = 0;
  198. while (fgets(str, MAXSTR, f_in) != NULL) {
  199. n_lines++;
  200. }
  201. if (n_lines == 0) {
  202. return;
  203. }
  204. rewind(f_in);
  205. /* create an array large enough to hold all lines in index.html */
  206. /* plus the entries that are to be added for the extension */
  207. /* plus one NULL terminator */
  208. /* and copy all lines from index.html into this */
  209. line = (char **)calloc(n_lines + 10, sizeof(char *));
  210. for (i = 0; i < (n_lines + 10); i++) {
  211. line[i] = NULL;
  212. }
  213. i = 0;
  214. while (fgets(str, MAXSTR, f_in) != NULL) {
  215. line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char));
  216. strcpy(line[i], str);
  217. i++;
  218. }
  219. /* create "Extensions" entry in html document if necessary and add a link to */
  220. /* this extension's HTML man index */
  221. new_ext_html(pkg_short_name, gisbase, line, major, minor, revision);
  222. /* write output to tmpfile */
  223. i = 0;
  224. while (line[i] != NULL) {
  225. fprintf(f_out, line[i]);
  226. i++;
  227. }
  228. fflush(f_out);
  229. /* close files */
  230. fclose(f_in);
  231. fclose(f_out);
  232. /* free memory */
  233. for (i = 0; i < (n_lines + 10); i++) {
  234. free(line[i]);
  235. }
  236. free(line);
  237. }
  238. void deregister_html(char *pkg_short_name, char *gisbase)
  239. {
  240. char file[MAXSTR];
  241. char str[MAXSTR];
  242. char **line;
  243. int n_lines, i;
  244. FILE *f_in, *f_out;
  245. /* check if index.html exists and is readable */
  246. sprintf(file, "%s/docs/html/index.html", gisbase);
  247. f_in = fopen(file, "r");
  248. if (f_in == NULL) {
  249. if (errno == ENOENT) {
  250. /* file does not exist */
  251. return;
  252. }
  253. else {
  254. /* sth. strange happened */
  255. fclose(f_in);
  256. print_error(ERR_REGISTER_HTML, "checking for file '%s': %s\n",
  257. file, strerror(errno));
  258. }
  259. }
  260. /* create a temporary index.html copy for write access */
  261. /* TODO: Do not hardcode temp paths */
  262. strcpy(TMP_HTML, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_HTML is a global variable */
  263. mkstemp(TMP_HTML);
  264. f_out = fopen(TMP_HTML, "w+");
  265. if (f_out == NULL) {
  266. print_error(ERR_REGISTER_HTML,
  267. "could not create temp file '%s': %s\n \
  268. Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_HTML, strerror(errno));
  269. }
  270. atexit(&exit_db); /* now need to register an at exit func to remove tmpdb automatically! */
  271. /* everything fine: create a shell command to copy modified HTML stuff on uninstall */
  272. if (VERBOSE) {
  273. sprintf(str,
  274. "cp -vf %s %s/docs/html/index.html ; chmod -v a+r %s/docs/html/index.html ;",
  275. TMP_HTML, gisbase, gisbase);
  276. }
  277. else {
  278. sprintf(str,
  279. "cp -f %s %s/docs/html/index.html &>%s ; chmod a+r %s/docs/html/index.html &>%s ;",
  280. TMP_HTML, gisbase, TMP_NULL, gisbase, TMP_NULL);
  281. }
  282. strcpy(HTML_CMD, str);
  283. /* count number of lines in index.html */
  284. n_lines = 0;
  285. while (fgets(str, MAXSTR, f_in) != NULL) {
  286. n_lines++;
  287. }
  288. if (n_lines == 0) {
  289. return;
  290. }
  291. rewind(f_in);
  292. /* create an array large enough to hold all lines in index.html */
  293. /* plus one NULL terminator */
  294. /* and copy all lines from index.html into this */
  295. line = (char **)calloc(n_lines + 1, sizeof(char *));
  296. for (i = 0; i < (n_lines + 1); i++) {
  297. line[i] = NULL;
  298. }
  299. i = 0;
  300. while (fgets(str, MAXSTR, f_in) != NULL) {
  301. line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char));
  302. strcpy(line[i], str);
  303. i++;
  304. }
  305. /* delete link to this extension's HTML manual from index.html */
  306. delete_ext_html(pkg_short_name, gisbase, line);
  307. /* write output to tmpfile */
  308. i = 0;
  309. while (line[i] != NULL) {
  310. fprintf(f_out, line[i]);
  311. i++;
  312. }
  313. fflush(f_out);
  314. /* close files */
  315. fclose(f_in);
  316. fclose(f_out);
  317. /* free memory */
  318. for (i = 0; i < (n_lines + 1); i++) {
  319. free(line[i]);
  320. }
  321. free(line);
  322. }
  323. /*
  324. Returns number of restored entries
  325. */
  326. int restore_html(char *gisbase)
  327. {
  328. char str[MAXSTR];
  329. char idx[MAXSTR];
  330. char ext_idx[MAXSTR];
  331. char dir[MAXSTR];
  332. char subdir[MAXSTR];
  333. char **line;
  334. int n_entries, n_lines, i;
  335. FILE *f_in, *f_out, *f_ext;
  336. DIR *dirp;
  337. DIR *subdirp;
  338. struct dirent *ep;
  339. int num_restored;
  340. int n_subdirs;
  341. int major, minor, revision;
  342. /* check if index.html exists and is readable */
  343. sprintf(idx, "%s/docs/html/index.html", gisbase);
  344. f_in = fopen(idx, "r");
  345. if (f_in == NULL) {
  346. if (errno == ENOENT) {
  347. /* file does not exist */
  348. return (0);
  349. }
  350. else {
  351. /* sth. strange happened */
  352. fclose(f_in);
  353. print_error(ERR_REGISTER_HTML, "checking for file '%s': %s\n",
  354. idx, strerror(errno));
  355. }
  356. }
  357. /* create a temporary index.html copy for write access */
  358. /* TODO: Do not hardcode temp paths */
  359. strcpy(TMP_HTML, "/tmp/grass.extensions.db.XXXXXX"); /* TMP_HTML is a global variable */
  360. mkstemp(TMP_HTML);
  361. f_out = fopen(TMP_HTML, "w+");
  362. if (f_out == NULL) {
  363. print_error(ERR_REGISTER_HTML,
  364. "could not create temp file '%s': %s\n \
  365. Make sure that directory /tmp exists on your system and you have write permission.\n", TMP_HTML, strerror(errno));
  366. }
  367. /* everything fine: create a shell command to install HTML stuff */
  368. if (VERBOSE) {
  369. sprintf(str,
  370. "cp -vf %s %s/docs/html/index.html ; chmod -v a+r %s/docs/html/index.html ;",
  371. TMP_HTML, gisbase, gisbase);
  372. }
  373. else {
  374. sprintf(str,
  375. "cp -f %s %s/docs/html/index.html &>%s ; chmod a+r %s/docs/html/index.html &>%s ;",
  376. TMP_HTML, gisbase, TMP_NULL, gisbase, TMP_NULL);
  377. }
  378. strcpy(HTML_CMD, str);
  379. atexit(&exit_db); /* now need to register an at exit func to remove tmpdb automatically! */
  380. /* allocate a pointer to the directory structure */
  381. sprintf(dir, "%s/docs/extensions", gisbase);
  382. dirp = opendir(dir);
  383. if (dirp == NULL) {
  384. /* directory does not exist or is not accessible */
  385. return (0);
  386. }
  387. /* PASS 1 */
  388. /* count number of subdirs in docs/extensions/ each new link will require one entry in index.html */
  389. n_entries = 0;
  390. n_subdirs = 0;
  391. while ((ep = readdir(dirp))) {
  392. sprintf(subdir, "%s/%s", dir, ep->d_name);
  393. if ((!strcmp(ep->d_name, ".")) || (!strcmp(ep->d_name, ".."))) {
  394. continue;
  395. }
  396. subdirp = opendir(subdir);
  397. if (subdirp == NULL) {
  398. continue;
  399. }
  400. n_subdirs++;
  401. closedir(subdirp);
  402. }
  403. closedir(dirp);
  404. /* count number of lines in menu.tcl */
  405. n_lines = 0;
  406. while (fgets(str, MAXSTR, f_in) != NULL) {
  407. n_lines++;
  408. }
  409. if (n_lines == 0) {
  410. return (0);
  411. }
  412. rewind(f_in);
  413. /* create an array large enough to hold all lines in index.html */
  414. /* plus one new entry to make a link for each extension */
  415. /* plus space for the new Extensions section */
  416. /* plus one NULL terminator */
  417. /* and copy all lines from menu.tcl into this */
  418. line = (char **)calloc(n_lines + n_subdirs + 10, sizeof(char *));
  419. for (i = 0; i < (n_lines + n_subdirs + 10); i++) {
  420. line[i] = NULL;
  421. }
  422. i = 0;
  423. while (fgets(str, MAXSTR, f_in) != NULL) {
  424. line[i] = (char *)malloc((1 + strlen(str)) * sizeof(char));
  425. strcpy(line[i], str);
  426. i++;
  427. }
  428. line[i] = NULL; /* add NULL terminator */
  429. /* PASS 2: re-create links if necessary */
  430. dirp = opendir(dir);
  431. num_restored = 0;
  432. while ((ep = readdir(dirp))) {
  433. sprintf(subdir, "%s/%s", dir, ep->d_name);
  434. if ((!strcmp(ep->d_name, ".")) || (!strcmp(ep->d_name, ".."))) {
  435. continue;
  436. }
  437. subdirp = opendir(subdir);
  438. if (subdirp == NULL) {
  439. continue;
  440. }
  441. closedir(subdirp);
  442. /* try to open extension's index.html file */
  443. sprintf(ext_idx, "%s/index.html", subdir);
  444. f_ext = fopen(ext_idx, "r");
  445. if (f_ext == NULL) {
  446. continue; /* cannot access index.html: skip to next extension */
  447. }
  448. major = 0;
  449. minor = 0;
  450. revision = 0;
  451. /* retrieve version information from extension's index.html */
  452. i = 0;
  453. while (fgets(str, MAXSTR, f_ext) != NULL) {
  454. if (strstr(str, "<title>") != NULL) {
  455. i = 1;
  456. break; /* this is the title line: that's all we need */
  457. }
  458. }
  459. if (i == 0) {
  460. continue; /* not a valid index.html: skip to next extension */
  461. }
  462. sscanf(strchr(str, '(') + sizeof(char), "%i.%i.%i", &major, &minor,
  463. &revision);
  464. new_ext_html(ep->d_name, gisbase, line, major, minor, revision);
  465. num_restored++;
  466. fclose(f_ext);
  467. }
  468. closedir(dirp);
  469. /* write output to tmpfile */
  470. i = 0;
  471. while (line[i] != NULL) {
  472. fprintf(f_out, line[i]);
  473. i++;
  474. }
  475. fflush(f_out);
  476. /* close remaining files */
  477. fclose(f_in);
  478. fclose(f_out);
  479. /* free memory */
  480. for (i = 0; i < (n_lines + n_subdirs + 10); i++) {
  481. free(line[i]);
  482. }
  483. free(line);
  484. return (num_restored);
  485. }