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