ReactOS  0.4.13-dev-247-g0f29b3f
bookmark.c
Go to the documentation of this file.
1 /* bookmark.c
2  *
3  * Copyright (c) 1992-2001 by Mike Gleason.
4  * All rights reserved.
5  *
6  */
7 
8 #include "syshdrs.h"
9 
10 #include "bookmark.h"
11 #include "util.h"
12 
13 /*
14  * The ~/.ncftp/bookmarks file contains a list of sites
15  * the user wants to remember.
16  *
17  * Unlike previous versions of the program, we now open/close
18  * the file every time we need it; That way we can have
19  * multiple ncftp processes changing the file. There is still
20  * a possibility that two different processes could be modifying
21  * the file at the same time.
22  */
23 
25 int gLoadedBm = 0;
27 int gNumBookmarks = 0;
29 
30 extern char gOurDirectoryPath[];
31 
32 /* Converts a pre-loaded Bookmark structure into a RFC 1738
33  * Uniform Resource Locator.
34  */
35 void
36 BookmarkToURL(BookmarkPtr bmp, char *url, size_t urlsize)
37 {
38  char pbuf[32];
39 
40  /* //<user>:<password>@<host>:<port>/<url-path> */
41  /* Note that if an absolute path is given,
42  * you need to escape the first entry, i.e. /pub -> %2Fpub
43  */
44  (void) Strncpy(url, "ftp://", urlsize);
45  if (bmp->user[0] != '\0') {
46  (void) Strncat(url, bmp->user, urlsize);
47  if (bmp->pass[0] != '\0') {
48  (void) Strncat(url, ":", urlsize);
49  (void) Strncat(url, "PASSWORD", urlsize);
50  }
51  (void) Strncat(url, "@", urlsize);
52  }
53  (void) Strncat(url, bmp->name, urlsize);
54  if (bmp->port != 21) {
55  (void) sprintf(pbuf, ":%u", (unsigned int) bmp->port);
56  (void) Strncat(url, pbuf, urlsize);
57  }
58  if (bmp->dir[0] == '/') {
59  /* Absolute URL path, must escape first slash. */
60  (void) Strncat(url, "/%2F", urlsize);
61  (void) Strncat(url, bmp->dir + 1, urlsize);
62  (void) Strncat(url, "/", urlsize);
63  } else if (bmp->dir[0] != '\0') {
64  (void) Strncat(url, "/", urlsize);
65  (void) Strncat(url, bmp->dir, urlsize);
66  (void) Strncat(url, "/", urlsize);
67  }
68 } /* BookmarkToURL */
69 
70 
71 
72 
73 void
75 {
76  (void) memset(bmp, 0, sizeof(Bookmark));
77 
78  bmp->xferType = 'I';
79  bmp->xferMode = 'S'; /* Use FTP protocol default as ours too. */
82  bmp->hasUTIME = kCommandAvailabilityUnknown;
84  bmp->isUnix = 1;
85  bmp->lastCall = (time_t) 0;
86  bmp->deleted = 0;
87 } /* SetBookmarkDefaults */
88 
89 
90 
91 
92 /* Used when converting hex strings to integral types. */
93 static int
95 {
96  switch (c) {
97  case '0':
98  case '1':
99  case '2':
100  case '3':
101  case '4':
102  case '5':
103  case '6':
104  case '7':
105  case '8':
106  case '9':
107  return (c - '0');
108  case 'a':
109  case 'b':
110  case 'c':
111  case 'd':
112  case 'e':
113  case 'f':
114  return (c - 'a' + 10);
115  case 'A':
116  case 'B':
117  case 'C':
118  case 'D':
119  case 'E':
120  case 'F':
121  return (c - 'A' + 10);
122 
123  }
124  return (-1); /* Error. */
125 } /* HexCharToNibble */
126 
127 
128 
129 
130 
131 /* Fills in a Bookmark structure based off of a line from the NcFTP
132  * "bookmarks" file.
133  */
134 int
136 {
137  char token[128];
138  char pass[128];
139  char *s, *d;
140  char *tokenend;
141  long L;
142  int i;
143  int result;
144  int n, n1, n2;
145 
147  s = line;
148  tokenend = token + sizeof(token) - 1;
149  result = -1;
150  for (i=1; ; i++) {
151  if (*s == '\0')
152  break;
153  /* Some tokens may need to have a comma in them. Since this is a
154  * field delimiter, these fields use \, to represent a comma, and
155  * \\ for a backslash. This chunk gets the next token, paying
156  * attention to the escaped stuff.
157  */
158  for (d = token; *s != '\0'; ) {
159  if ((*s == '\\') && (s[1] != '\0')) {
160  if (d < tokenend)
161  *d++ = s[1];
162  s += 2;
163  } else if (*s == ',') {
164  ++s;
165  break;
166  } else if ((*s == '$') && (s[1] != '\0') && (s[2] != '\0')) {
167  n1 = HexCharToNibble(s[1]);
168  n2 = HexCharToNibble(s[2]);
169  if ((n1 >= 0) && (n2 >= 0)) {
170  n = (n1 << 4) | n2;
171  if (d < tokenend)
172  *(unsigned char *)d++ = (unsigned int) n;
173  }
174  s += 3;
175  } else {
176  if (d < tokenend)
177  *d++ = *s;
178  ++s;
179  }
180  }
181  *d = '\0';
182  switch(i) {
183  case 1: (void) STRNCPY(bmp->bookmarkName, token); break;
184  case 2: (void) STRNCPY(bmp->name, token); break;
185  case 3: (void) STRNCPY(bmp->user, token); break;
186  case 4: (void) STRNCPY(bmp->pass, token); break;
187  case 5: (void) STRNCPY(bmp->acct, token); break;
188  case 6: (void) STRNCPY(bmp->dir, token);
189  result = 0; /* Good enough to have these fields. */
190  break;
191  case 7:
192  if (token[0] != '\0')
193  bmp->xferType = (int) token[0];
194  break;
195  case 8:
196  /* Most of the time, we won't have a port. */
197  if (token[0] == '\0')
198  bmp->port = (unsigned int) kDefaultFTPPort;
199  else
200  bmp->port = (unsigned int) atoi(token);
201  break;
202  case 9:
203  (void) sscanf(token, "%lx", &L);
204  bmp->lastCall = (time_t) L;
205  break;
206  case 10: bmp->hasSIZE = atoi(token); break;
207  case 11: bmp->hasMDTM = atoi(token); break;
208  case 12: bmp->hasPASV = atoi(token); break;
209  case 13: bmp->isUnix = atoi(token);
210  result = 3; /* Version 3 had all fields to here. */
211  break;
212  case 14: (void) STRNCPY(bmp->lastIP, token); break;
213  case 15: (void) STRNCPY(bmp->comment, token); break;
214  case 16:
215  case 17:
216  case 18:
217  case 19:
218  break;
219  case 20: bmp->xferMode = token[0];
220  result = 7; /* Version 7 has all fields to here. */
221  break;
222  case 21: bmp->hasUTIME = atoi(token);
223  break;
224  case 22: (void) STRNCPY(bmp->ldir, token);
225  result = 8; /* Version 8 has all fields to here. */
226  break;
227  default:
228  result = 99; /* Version >8 ? */
229  goto done;
230  }
231  }
232 done:
233 
234  /* Decode password, if it was base-64 encoded. */
235  if (strncmp(bmp->pass, kPasswordMagic, kPasswordMagicLen) == 0) {
237  (void) STRNCPY(bmp->pass, pass);
238  }
239  return (result);
240 } /* ParseHostLine */
241 
242 
243 
244 
245 void
247 {
248  if (fp != NULL)
249  (void) fclose(fp);
250 } /* CloseBookmarkFile */
251 
252 
253 
254 
255 
256 int
258 {
259  char line[512];
260 
261  while (FGets(line, sizeof(line), fp) != NULL) {
262  if (ParseHostLine(line, bmp) >= 0)
263  return (0);
264  }
265  return (-1);
266 } /* GetNextBookmark */
267 
268 
269 
270 
271 /* Opens a NcFTP 2.x or 3.x style bookmarks file, and sets the file pointer
272  * so that it is ready to read the first data line.
273  */
274 FILE *
275 OpenBookmarkFile(int *numBookmarks0)
276 {
277  char pathName[256], path2[256];
278  char line[256];
279  FILE *fp;
280  int version;
281  int numBookmarks;
282  Bookmark junkbm;
283 
284  if (gOurDirectoryPath[0] == '\0')
285  return NULL; /* Don't create in root directory. */
286  (void) OurDirectoryPath(pathName, sizeof(pathName), kBookmarkFileName);
287  fp = fopen(pathName, FOPEN_READ_TEXT);
288  if (fp == NULL) {
289  /* See if it exists under the old name. */
291  if (rename(path2, pathName) == 0) {
292  /* Rename succeeded, now open it. */
293  fp = fopen(pathName, FOPEN_READ_TEXT);
294  if (fp == NULL)
295  return NULL;
296  }
297  return NULL; /* Okay to not have one yet. */
298  }
299 
300  (void) _chmod(pathName, 00600);
301  if (FGets(line, sizeof(line), fp) == NULL) {
302  (void) fprintf(stderr, "%s: invalid format.\n", pathName);
303  (void) fclose(fp);
304  return NULL;
305  }
306 
307  /* Sample line we're looking for:
308  * "NcFTP bookmark-file version: 8"
309  */
310  version = -1;
311  (void) sscanf(line, "%*s %*s %*s %d", &version);
313  if (version < 0) {
314  (void) fprintf(stderr, "%s: invalid format, or bad version.\n", pathName);
315  (void) fclose(fp);
316  return NULL;
317  }
318  (void) STRNCPY(path2, pathName);
319  (void) sprintf(line, ".v%d", version);
320  (void) STRNCAT(path2, line);
321  (void) rename(pathName, path2);
322  (void) fprintf(stderr, "%s: old version.\n", pathName);
323  (void) fclose(fp);
324  return NULL;
325  }
326 
327  /* Sample line we're looking for:
328  * "Number of entries: 28" or "# # # 1"
329  */
330  numBookmarks = -1;
331 
332  /* At the moment, we can't trust the number stored in the
333  * file. It's there for future use.
334  */
335  if (FGets(line, sizeof(line), fp) == NULL) {
336  (void) fprintf(stderr, "%s: invalid format.\n", pathName);
337  (void) fclose(fp);
338  return NULL;
339  }
340 
341  if (numBookmarks0 == (int *) 0) {
342  /* If the caller doesn't care how many bookmarks are *really*
343  * in the file, then we can return now.
344  */
345  return(fp);
346  }
347 
348  /* Otherwise, we have to read through the whole file because
349  * unfortunately the header line can't be trusted.
350  */
351  for (numBookmarks = 0; ; numBookmarks++) {
352  if (GetNextBookmark(fp, &junkbm) < 0)
353  break;
354  }
355 
356  /* Now we have to re-open and re-position the file.
357  * We don't use rewind() because it doesn't always work.
358  * This introduces a race condition, but the bookmark
359  * functionality wasn't designed to be air-tight.
360  */
361  CloseBookmarkFile(fp);
362  fp = fopen(pathName, FOPEN_READ_TEXT);
363  if (fp == NULL)
364  return (NULL);
365  if (FGets(line, sizeof(line), fp) == NULL) {
366  (void) fprintf(stderr, "%s: invalid format.\n", pathName);
367  (void) fclose(fp);
368  return NULL;
369  }
370 
371  if (FGets(line, sizeof(line), fp) == NULL) {
372  (void) fprintf(stderr, "%s: invalid format.\n", pathName);
373  (void) fclose(fp);
374  return NULL;
375  }
376 
377  /* NOW we're done. */
378  *numBookmarks0 = numBookmarks;
379  return (fp);
380 } /* OpenBookmarkFile */
381 
382 
383 
384 
385 /* Looks for a saved bookmark by the abbreviation given. */
386 int
387 GetBookmark(const char *const bmabbr, Bookmark *bmp)
388 {
389  FILE *fp;
390  char line[512];
391  Bookmark byHostName;
392  Bookmark byHostAbbr;
393  Bookmark byBmAbbr;
394  size_t byBmNameFlag = 0;
395  size_t byBmAbbrFlag = 0;
396  size_t byHostNameFlag = 0;
397  size_t byHostAbbrFlag = 0;
398  int result = -1;
399  int exactMatch = 0;
400  size_t bmabbrLen;
401  char *cp;
402 
403  fp = OpenBookmarkFile(NULL);
404  if (fp == NULL)
405  return (-1);
406 
407  bmabbrLen = strlen(bmabbr);
408  while (FGets(line, sizeof(line), fp) != NULL) {
409  if (ParseHostLine(line, bmp) < 0)
410  continue;
411  if (ISTREQ(bmp->bookmarkName, bmabbr)) {
412  /* Exact match, done. */
413  byBmNameFlag = bmabbrLen;
414  exactMatch = 1;
415  break;
416  } else if (ISTRNEQ(bmp->bookmarkName, bmabbr, bmabbrLen)) {
417  /* Remember this one, it matched an abbreviated
418  * bookmark name.
419  */
420  byBmAbbr = *bmp;
421  byBmAbbrFlag = bmabbrLen;
422  } else if (ISTREQ(bmp->name, bmabbr)) {
423  /* Remember this one, it matched a full
424  * host name.
425  */
426  byHostName = *bmp;
427  byHostNameFlag = bmabbrLen;
428  } else if ((cp = strchr(bmp->name, '.')) != NULL) {
429  /* See if it matched part of the hostname. */
430  if (ISTRNEQ(bmp->name, "ftp", 3)) {
431  cp = cp + 1;
432  } else if (ISTRNEQ(bmp->name, "www", 3)) {
433  cp = cp + 1;
434  } else {
435  cp = bmp->name;
436  }
437  if (ISTRNEQ(cp, bmabbr, bmabbrLen)) {
438  /* Remember this one, it matched a full
439  * host name.
440  */
441  byHostAbbr = *bmp;
442  byHostAbbrFlag = bmabbrLen;
443  }
444  }
445  }
446 
447  if (gBookmarkMatchMode == 0) {
448  /* Only use a bookmark when the exact
449  * bookmark name was used.
450  */
451  if (exactMatch != 0) {
452  result = 0;
453  }
454  } else {
455  /* Pick the best match, if any. */
456  if (byBmNameFlag != 0) {
457  /* *bmp is already set. */
458  result = 0;
459  } else if (byBmAbbrFlag != 0) {
460  result = 0;
461  *bmp = byBmAbbr;
462  } else if (byHostNameFlag != 0) {
463  result = 0;
464  *bmp = byHostName;
465  } else if (byHostAbbrFlag != 0) {
466  result = 0;
467  *bmp = byHostAbbr;
468  }
469  }
470 
471  if (result != 0)
472  memset(bmp, 0, sizeof(Bookmark));
473 
474  CloseBookmarkFile(fp);
475  return (result);
476 } /* GetBookmark */
477 
478 
479 
480 
481 static int
482 BookmarkSortProc(const void *a, const void *b)
483 {
484  return (ISTRCMP((*(Bookmark *)a).bookmarkName, (*(Bookmark *)b).bookmarkName));
485 } /* BookmarkSortProc */
486 
487 
488 
489 static int
490 BookmarkSearchProc(const void *key, const void *b)
491 {
492  return (ISTRCMP((char *) key, (*(Bookmark *)b).bookmarkName));
493 } /* BookmarkSearchProc */
494 
495 
496 
499 {
501 } /* SearchBookmarkTable */
502 
503 
504 
505 
506 void
508 {
509  if ((gBookmarkTable == NULL) || (gNumBookmarks < 2))
510  return;
511 
512  /* Sorting involves swapping entire Bookmark structures.
513  * Normally the proper thing to do is to use an array
514  * of pointers to Bookmarks and sort them, but even
515  * these days a large bookmark list can be sorted in
516  * the blink of an eye.
517  */
519 } /* SortBookmarks */
520 
521 
522 
523 int
525 {
526  int i, nb;
527  FILE *infp;
528 
529  infp = OpenBookmarkFile(&nb);
530  if (infp == NULL) {
531  nb = 0;
532  }
533  if ((nb != gNumBookmarks) && (gBookmarkTable != NULL)) {
534  /* Re-loading the table from disk. */
535  gBookmarkTable = (Bookmark *) realloc(gBookmarkTable, (size_t) (nb + 1) * sizeof(Bookmark));
536  memset(gBookmarkTable, 0, (nb + 1) * sizeof(Bookmark));
537  } else {
538  gBookmarkTable = calloc((size_t) (nb + 1), (size_t) sizeof(Bookmark));
539  }
540 
541  if (gBookmarkTable == NULL) {
542  CloseBookmarkFile(infp);
543  return (-1);
544  }
545 
546  for (i=0; i<nb; i++) {
547  if (GetNextBookmark(infp, gBookmarkTable + i) < 0) {
548  break;
549  }
550  }
551  gNumBookmarks = i;
552 
553  CloseBookmarkFile(infp);
554  SortBookmarks();
555  return (0);
556 } /* LoadBookmarkTable */
557 
558 
559 
560 
561 /* Some characters need to be escaped so the file is editable and can
562  * be parsed correctly the next time it is read.
563  */
564 static char *
565 BmEscapeTok(char *dst, size_t dsize, char *src)
566 {
567  char *dlim = dst + dsize - 1;
568  char *dst0 = dst;
569  int c;
570 
571  while ((c = *src) != '\0') {
572  src++;
573  if ((c == '\\') || (c == ',') || (c == '$')) {
574  /* These need to be escaped. */
575  if ((dst + 1) < dlim) {
576  *dst++ = '\\';
577  *dst++ = c;
578  }
579  } else if (!isprint(c)) {
580  /* Escape non-printing characters. */
581  if ((dst + 2) < dlim) {
582  (void) sprintf(dst, "$%02x", c);
583  dst += 3;
584  }
585  } else {
586  if (dst < dlim)
587  *dst++ = c;
588  }
589  }
590  *dst = '\0';
591  return (dst0);
592 } /* BmEscapeTok */
593 
594 
595 
596 
597 /* Converts a Bookmark into a text string, and writes it to the saved
598  * bookmarks file.
599  */
600 static int
601 WriteBmLine(Bookmark *bmp, FILE *outfp, int savePassword)
602 {
603  char tok[256];
604  char pass[160];
605 
606  if (fprintf(outfp, "%s", bmp->bookmarkName) < 0) return (-1) ;/*1*/
607  if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->name)) < 0) return (-1) ;/*2*/
608  if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->user)) < 0) return (-1) ;/*3*/
609  if ((bmp->pass[0] != '\0') && (savePassword == 1)) {
611  ToBase64(pass + kPasswordMagicLen, bmp->pass, strlen(bmp->pass), 1);
612  if (fprintf(outfp, ",%s", pass) < 0) return (-1) ;/*4*/
613  } else {
614  if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*4*/
615  }
616  if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->acct)) < 0) return (-1) ;/*5*/
617  if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->dir)) < 0) return (-1) ;/*6*/
618  if (fprintf(outfp, ",%c", bmp->xferType) < 0) return (-1) ;/*7*/
619  if (fprintf(outfp, ",%u", (unsigned int) bmp->port) < 0) return (-1) ;/*8*/
620  if (fprintf(outfp, ",%lu", (unsigned long) bmp->lastCall) < 0) return (-1) ;/*9*/
621  if (fprintf(outfp, ",%d", bmp->hasSIZE) < 0) return (-1) ;/*10*/
622  if (fprintf(outfp, ",%d", bmp->hasMDTM) < 0) return (-1) ;/*11*/
623  if (fprintf(outfp, ",%d", bmp->hasPASV) < 0) return (-1) ;/*12*/
624  if (fprintf(outfp, ",%d", bmp->isUnix) < 0) return (-1) ;/*13*/
625  if (fprintf(outfp, ",%s", bmp->lastIP) < 0) return (-1) ;/*14*/
626  if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->comment)) < 0) return (-1) ;/*15*/
627  if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*16*/
628  if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*17*/
629  if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*18*/
630  if (fprintf(outfp, ",%s", "") < 0) return (-1) ;/*19*/
631  if (fprintf(outfp, ",%c", bmp->xferMode) < 0) return (-1) ;/*20*/
632  if (fprintf(outfp, ",%d", bmp->hasUTIME) < 0) return (-1) ;/*21*/
633  if (fprintf(outfp, ",%s", BmEscapeTok(tok, sizeof(tok), bmp->ldir)) < 0) return (-1) ;/*22*/
634  if (fprintf(outfp, "\n") < 0) return (-1) ;
635  if (fflush(outfp) < 0) return (-1);
636  return (0);
637 } /* WriteBmLine */
638 
639 
640 
641 static int
643 {
644  char pidStr[32];
645  char pathName[256], path2[256];
646 
648  (void) OurDirectoryPath(pathName, sizeof(pathName), kTmpBookmarkFileName);
649  (void) sprintf(pidStr, "-%u.txt", (unsigned int) getpid());
650  (void) STRNCAT(pathName, pidStr);
651 
652  (void) remove(path2);
653  if (rename(pathName, path2) < 0) {
654  return (-1);
655  }
656  return (0);
657 } /* SwapBookmarkFiles */
658 
659 
660 
661 
662 
663 
664 /* Saves a Bookmark structure into the bookmarks file. */
665 FILE *
667 {
668  FILE *outfp;
669  char pidStr[32];
670  char pathName[256], path2[256];
671 
672  if (gOurDirectoryPath[0] == '\0')
673  return (NULL); /* Don't create in root directory. */
674 
676  (void) OurDirectoryPath(pathName, sizeof(pathName), kTmpBookmarkFileName);
677  (void) sprintf(pidStr, "-%u.txt", (unsigned int) getpid());
678  (void) STRNCAT(pathName, pidStr);
679 
680  outfp = fopen(pathName, FOPEN_WRITE_TEXT);
681  if (outfp == NULL) {
682  (void) fprintf(stderr, "Could not save bookmark.\n");
683  perror(pathName);
684  return (NULL);
685  }
686  (void) _chmod(pathName, 00600);
687  if (nb > 0) {
688  if (fprintf(outfp, "NcFTP bookmark-file version: %d\nNumber of bookmarks: %d\n", kBookmarkVersion, nb) < 0) {
689  (void) fprintf(stderr, "Could not save bookmark.\n");
690  perror(pathName);
691  (void) fclose(outfp);
692  return (NULL);
693  }
694  } else {
695  if (fprintf(outfp, "NcFTP bookmark-file version: %d\nNumber of bookmarks: ??\n", kBookmarkVersion) < 0) {
696  (void) fprintf(stderr, "Could not save bookmark.\n");
697  perror(pathName);
698  (void) fclose(outfp);
699  return (NULL);
700  }
701  }
702 
703  return (outfp);
704 } /* OpenTmpBookmarkFile */
705 
706 
707 
708 
709 int
711 {
712  int i;
713  FILE *outfp;
714  int nb;
715 
716  if ((gNumBookmarks < 1) || (gBookmarkTable == NULL))
717  return (0); /* Nothing to save. */
718 
719  /* Get a count of live bookmarks. */
720  for (i=0, nb=0; i<gNumBookmarks; i++) {
721  if (gBookmarkTable[i].deleted == 0)
722  nb++;
723  }
724  outfp = OpenTmpBookmarkFile(nb);
725  if (outfp == NULL) {
726  return (-1);
727  }
728 
729  for (i=0; i<gNumBookmarks; i++) {
730  if (gBookmarkTable[i].deleted == 0) {
731  if (WriteBmLine(gBookmarkTable + i, outfp, 1) < 0) {
732  CloseBookmarkFile(outfp);
733  return (-1);
734  }
735  }
736  }
737  CloseBookmarkFile(outfp);
738  if (SwapBookmarkFiles() < 0) {
739  return (-1);
740  }
741  return (0);
742 } /* SaveBookmarkTable */
743 
744 
745 
746 /* Saves a Bookmark structure into the bookmarks file. */
747 int
748 PutBookmark(Bookmark *bmp, int savePassword)
749 {
750  FILE *infp, *outfp;
751  char line[256];
752  char bmAbbr[64];
753  int replaced = 0;
754  size_t len;
755 
756  outfp = OpenTmpBookmarkFile(0);
757  if (outfp == NULL)
758  return (-1);
759 
760  (void) STRNCPY(bmAbbr, bmp->bookmarkName);
761  (void) STRNCAT(bmAbbr, ",");
762  len = strlen(bmAbbr);
763 
764  /* This may fail the first time we ever save a bookmark. */
765  infp = OpenBookmarkFile(NULL);
766  if (infp != NULL) {
767  while (FGets(line, sizeof(line), infp) != NULL) {
768  if (strncmp(line, bmAbbr, len) == 0) {
769  /* Replace previous entry. */
770  if (WriteBmLine(bmp, outfp, savePassword) < 0) {
771  (void) fprintf(stderr, "Could not save bookmark.\n");
772  perror("reason");
773  (void) fclose(outfp);
774  }
775  replaced = 1;
776  } else {
777  if (fprintf(outfp, "%s\n", line) < 0) {
778  (void) fprintf(stderr, "Could not save bookmark.\n");
779  perror("reason");
780  (void) fclose(outfp);
781  return (-1);
782  }
783  }
784  }
785  CloseBookmarkFile(infp);
786  }
787 
788  if (replaced == 0) {
789  /* Add it as a new bookmark. */
790  if (WriteBmLine(bmp, outfp, savePassword) < 0) {
791  (void) fprintf(stderr, "Could not save bookmark.\n");
792  perror("reason");
793  (void) fclose(outfp);
794  return (-1);
795  }
796  }
797 
798  if (fclose(outfp) < 0) {
799  (void) fprintf(stderr, "Could not save bookmark.\n");
800  perror("reason");
801  return (-1);
802  }
803 
804  if (SwapBookmarkFiles() < 0) {
805  (void) fprintf(stderr, "Could not rename bookmark file.\n");
806  perror("reason");
807  return (-1);
808  }
809  return (0);
810 } /* PutBookmark */
811 
812 
813 
814 
815 /* Tries to generate a bookmark abbreviation based off of the hostname. */
816 void
817 DefaultBookmarkName(char *dst, size_t siz, char *src)
818 {
819  char str[128];
820  const char *token;
821  const char *cp;
822 
823  (void) STRNCPY(str, src);
824 
825  /* Pick the first "significant" part of the hostname. Usually
826  * this is the first word in the name, but if it's something like
827  * ftp.unl.edu, we would want to choose "unl" and not "ftp."
828  */
829  token = str;
830  if ((token = strtok(str, ".")) == NULL)
831  token = str;
832  else if ((ISTRNEQ(token, "ftp", 3)) || (ISTRNEQ(token, "www", 3))) {
833  if ((token = strtok(NULL, ".")) == NULL)
834  token = "";
835  }
836  for (cp = token; ; cp++) {
837  if (*cp == '\0') {
838  /* Token was all digits, like an IP address perhaps. */
839  token = "";
840  }
841  if (!isdigit((int) *cp))
842  break;
843  }
844  (void) Strncpy(dst, token, siz);
845 } /* DefaultBookmarkName */
#define realloc
Definition: debug_ros.c:6
#define kOldBookmarkFileName
Definition: bookmark.h:40
static const WCHAR path2[]
Definition: path.c:29
int gLoadedBm
Definition: bookmark.c:25
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define kDefaultFTPPort
Definition: ncftp.h:312
#define kPasswordMagic
Definition: util.h:47
#define kTmpBookmarkFileName
Definition: bookmark.h:39
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define kPasswordMagicLen
Definition: util.h:48
#define kCommandAvailabilityUnknown
Definition: ncftp.h:379
GLdouble n
Definition: glext.h:7729
char * OurDirectoryPath(char *const dst, const size_t siz, const char *const fname)
Definition: util.c:486
#define ISTRNEQ(a, b, s)
Definition: util.h:34
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
#define FOPEN_WRITE_TEXT
Definition: syshdrs.h:83
int GetNextBookmark(FILE *fp, Bookmark *bmp)
Definition: bookmark.c:257
BookmarkPtr SearchBookmarkTable(const char *key)
Definition: bookmark.c:498
#define kBookmarkVersion
Definition: bookmark.h:32
int gBookmarkMatchMode
Definition: bookmark.c:26
static int BookmarkSortProc(const void *a, const void *b)
Definition: bookmark.c:482
#define ISTREQ(a, b)
Definition: util.h:33
#define sprintf(buf, format,...)
Definition: sprintf.c:55
pass
Definition: typegen.h:24
char * Strncat(char *const, const char *const, const size_t)
Definition: Strncat.c:13
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ int __cdecl rename(_In_z_ const char *_OldFilename, _In_z_ const char *_NewFilename)
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
BookmarkPtr gBookmarkTable
Definition: bookmark.c:28
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
void BookmarkToURL(BookmarkPtr bmp, char *url, size_t urlsize)
Definition: bookmark.c:36
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
int SaveBookmarkTable(void)
Definition: bookmark.c:710
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
static int HexCharToNibble(int c)
Definition: bookmark.c:94
char gOurDirectoryPath[]
Definition: util.c:17
Definition: parser.c:48
static int BookmarkSearchProc(const void *key, const void *b)
Definition: bookmark.c:490
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define ISTRCMP
Definition: util.h:28
#define isdigit(c)
Definition: acclib.h:68
_Check_return_ _CRTIMP int __cdecl _chmod(_In_z_ const char *_Filename, _In_ int _Mode)
#define FOPEN_READ_TEXT
Definition: syshdrs.h:82
#define STRNCAT(d, s)
Definition: Strn.h:48
void ToBase64(void *dst0, const void *src0, size_t n, int terminate)
Definition: util.c:83
char * FGets(char *, size_t, FILE *)
Definition: util.c:111
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
int GetBookmark(const char *const bmabbr, Bookmark *bmp)
Definition: bookmark.c:387
_CRTIMP int __cdecl getpid(void)
#define d
Definition: ke_i.h:81
Definition: pbuf.h:79
static const WCHAR url[]
Definition: encode.c:1432
const GLubyte * c
Definition: glext.h:8905
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define kBookmarkMinVersion
Definition: bookmark.h:33
int n1
Definition: dwarfget.c:148
BITMAP bmp
Definition: alphablend.c:62
char line[200]
Definition: main.c:97
static const WCHAR L[]
Definition: oid.c:1250
FILE * OpenBookmarkFile(int *numBookmarks0)
Definition: bookmark.c:275
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
GLenum src
Definition: glext.h:6340
int LoadBookmarkTable(void)
Definition: bookmark.c:524
int PutBookmark(Bookmark *bmp, int savePassword)
Definition: bookmark.c:748
void SetBookmarkDefaults(BookmarkPtr bmp)
Definition: bookmark.c:74
static int WriteBmLine(Bookmark *bmp, FILE *outfp, int savePassword)
Definition: bookmark.c:601
int n2
Definition: dwarfget.c:148
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
void FromBase64(void *dst0, const void *src0, size_t n, int terminate)
Definition: util.c:128
__kernel_time_t time_t
Definition: linux.h:252
void CloseBookmarkFile(FILE *fp)
Definition: bookmark.c:246
char * Strncpy(char *const, const char *const, const size_t)
Definition: Strncpy.c:11
GLenum GLenum dst
Definition: glext.h:6340
int ParseHostLine(char *line, BookmarkPtr bmp)
Definition: bookmark.c:135
char * strtok(char *String, const char *Delimiters)
Definition: utclib.c:338
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define isprint(c)
Definition: acclib.h:73
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
POINT cp
Definition: magnifier.c:61
#define calloc
Definition: rosglue.h:14
void SortBookmarks(void)
Definition: bookmark.c:507
Bookmark gBm
Definition: bookmark.c:24
#define c
Definition: ke_i.h:80
FILE * stderr
int gNumBookmarks
Definition: bookmark.c:27
void DefaultBookmarkName(char *dst, size_t siz, char *src)
Definition: bookmark.c:817
static char * BmEscapeTok(char *dst, size_t dsize, char *src)
Definition: bookmark.c:565
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
FILE * OpenTmpBookmarkFile(int nb)
Definition: bookmark.c:666
int remove
Definition: msacm.c:1353
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define kBookmarkFileName
Definition: bookmark.h:37
Definition: path.c:42
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define bsearch
static int SwapBookmarkFiles(void)
Definition: bookmark.c:642