3 |7 | 8 |4 | You feel somewhat disoriented as you pass through... 5 |
6 |
9 | This is the Interactive Fiction Archive at 10 | www.ifarchive.org. 11 |
12 | 13 |14 | You may be interested in... 15 |
16 | 17 |25 | The 26 | list of all directories 27 | is a table of contents of the entire Archive, in order. 28 | The 29 | list of files, sorted by date 30 | is a (long) index of every file. 31 | You can also see the entries of the 32 | past week, 33 | past month, 34 | past three months, 35 | or 36 | past year. 37 |
38 | 39 |40 | Or, go delving into the hierarchical tree shown here. 41 |
42 | 43 | -------------------------------------------------------------------------------- /lib/dirlist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |19 | About the IF-Archive. 20 |
21 | 22 |31 | Enter the Archive 32 |
33 | 34 |19 | {?interval} 20 | This page lists the most recent {interval} of files in the Archive, 21 | sorted by date. 22 | {:} 23 | This page lists every file in the Archive, sorted by date. 24 | {/} 25 | (The last update of the file, not the date it first entered the 26 | Archive.) Note that this list is based on filesystem timestamps, 27 | which may be inaccurate -- or just plain wrong -- for various reasons. 28 | Please do not consider them infallible. 29 |
30 | 31 |40 | About the IF-Archive. 41 |
42 | 43 |44 | List of all directories. 45 |
46 | 47 |48 | Enter the Archive 49 |
50 | 51 |\n");
269 | headerpara = TRUE;
270 | }
271 | if (headerstrraw && headerstrraw[0]) {
272 | headerstrraw = append_string(headerstrraw, "\n");
273 | }
274 | }
275 | continue;
276 | }
277 |
278 | if (indent == 0 && *bx) {
279 | char *cx2, *id;
280 | int len;
281 |
282 | if (file) {
283 | if (filestr) {
284 | hash_put(file, "desc", filestr);
285 | if (is_string_nonwhite(filestr))
286 | hash_put(file, "hasdesc", "1");
287 | filestr = NULL;
288 | }
289 | if (filestrraw) {
290 | char *dx = new_string_esc_xml(filestrraw);
291 | trim_extra_newlines(dx);
292 | hash_put(file, "xmldesc", dx);
293 | if (is_string_nonwhite(filestrraw))
294 | hash_put(file, "hasxmldesc", "1");
295 | filestrraw = NULL;
296 | }
297 | hash_put(filelist, (char *)hash_get(file, "rawname"), file);
298 | file = NULL;
299 | }
300 |
301 | file = new_hash();
302 | filestr = NULL;
303 | filestrraw = NULL;
304 | firstindent = -1;
305 |
306 | for (cx2 = bx; *cx2 && *cx2 != ' '; cx2++);
307 | len = cx2-bx;
308 | id = (char *)malloc(sizeof(char) * (len+1));
309 | strncpy(id, bx, len);
310 | id[len] = '\0';
311 |
312 | while (*cx2 == ' ')
313 | cx2++;
314 | if (*cx2) {
315 | firstindent = (cx2-buf);
316 | filestr = append_string_esc(NULL, cx2, 0);
317 | filestr = append_string(filestr, "\n");
318 | filestrraw = append_string(NULL, cx2);
319 | filestrraw = append_string(filestrraw, "\n");
320 | brackets = bracket_count(cx2);
321 | }
322 | else {
323 | firstindent = -1;
324 | filestr = new_string("");
325 | filestrraw = new_string("");
326 | }
327 |
328 | hash_put(file, "rawname", id);
329 | hash_put_escurl(file, "name", "nameurl", id);
330 | hash_put_escxml(file, "namexml", id);
331 | hash_put(file, "dir", (char *)hash_get(dir, "dir"));
332 | }
333 | else {
334 | if (strlen(bx)) {
335 | if (firstindent < 0) {
336 | firstindent = indent;
337 | brackets = 0;
338 | }
339 | if ((firstindent != indent) && (brackets == 0)) {
340 | filestr = append_string(filestr, "
");
341 | filestrraw = append_spaces(filestrraw, indent-firstindent);
342 | }
343 | filestr = append_string_esc(filestr, bx, 0);
344 | filestr = append_string(filestr, "\n");
345 | filestrraw = append_string(filestrraw, bx);
346 | brackets += bracket_count(bx);
347 | }
348 | filestrraw = append_string(filestrraw, "\n");
349 | }
350 | }
351 |
352 | fclose(infl);
353 |
354 | exclude.do_exclude = doexclude;
355 | for (ix = 0; ix < EXCLUDESIZE; ix++)
356 | exclude.allowed[ix][0] = '\0';
357 |
358 | sprintf(buf, "%s/no-index-entry", indir);
359 | infl = fopen(buf, "r");
360 | if (!infl) {
361 | perror(buf);
362 | printf("Cannot open no-index-entry file. Goodbye.\n");
363 | return FALSE;
364 | }
365 |
366 | ix = 0;
367 | while (!feof(infl) && (ix < EXCLUDESIZE)) {
368 | fgets(exclude.allowed[ix], MAXPATHLEN, infl);
369 |
370 | jx = strlen(exclude.allowed[ix]);
371 | if ((jx > 0) && exclude.allowed[ix][jx-1] == '\n')
372 | exclude.allowed[ix][jx-1] = '\0';
373 | ix++;
374 | }
375 | fclose(infl);
376 |
377 | /* Do an actual scan of the tree and write in any directories
378 | we missed. */
379 | if (treedir)
380 | scan_directory(dirlist, treedir, ROOTNAME, NULL, NULL, &exclude, domd5);
381 |
382 | /* Now we have to buzz through and assign subdirectories. */
383 | {
384 | contextsubdir_t con;
385 | con.dirlist = dirlist;
386 | hash_iterate(dirlist, &subdir_thunk, &con);
387 | }
388 |
389 | return 1;
390 | }
391 |
392 | static int check_exclude(exclude_t *exclude, const char *name)
393 | {
394 | int i;
395 |
396 | for (i = 0; i < EXCLUDESIZE; i++) {
397 | if (exclude->allowed[i][0] == '\0')
398 | break;
399 | if (strncmp(name, exclude->allowed[i], strlen(exclude->allowed[i])) == 0)
400 | return 0;
401 | }
402 |
403 | fprintf(stderr,"File without index entry: %s\n", name);
404 | return (exclude->do_exclude == 0) ? 0 : 1;
405 | }
406 |
407 | static void scan_directory(hash_t *dirlist, char *treedir, char *dirname,
408 | hash_t *parentlist, char *parentdir, exclude_t *exclude, int domd5)
409 | {
410 | DIR *udir;
411 | hash_t *dir, *filelist;
412 | struct dirent *ent;
413 | struct stat sta, sta2;
414 | char pathname[MAXPATHLEN];
415 | char dirname2[MAXPATHLEN];
416 |
417 | if (verbose)
418 | printf("Scanning %s...\n", dirname);
419 |
420 | dir = hash_get(dirlist, dirname);
421 | if (!dir) {
422 | show_warning2("Unable to find directory.", dirname);
423 | return;
424 | }
425 | filelist = hash_get(dir, "@files");
426 |
427 | sprintf(pathname, "%s/%s", treedir, dirname);
428 |
429 | udir = opendir(pathname);
430 | if (!udir) {
431 | show_warning2("Unable to open directory.", pathname);
432 | return;
433 | }
434 |
435 | while ((ent = readdir(udir)) != NULL) {
436 | char *fname = ent->d_name;
437 | if (*fname == '\0' || *fname == '.')
438 | continue;
439 |
440 | sprintf(dirname2, "%s/%s", dirname, fname);
441 | sprintf(pathname, "%s/%s/%s", treedir, dirname, fname);
442 |
443 | if (lstat(pathname, &sta)) {
444 | show_warning2("Unable to lstat.", pathname);
445 | continue;
446 | }
447 |
448 | if (S_ISLNK(sta.st_mode)) {
449 | /* got a symlink */
450 | char linkname[MAXPATHLEN+1];
451 | int linklen;
452 | linklen = readlink(pathname, linkname, MAXPATHLEN);
453 | if (linklen <= 0) {
454 | show_warning2("Unable to readlink.", pathname);
455 | }
456 | else {
457 | linkname[linklen] = '\0';
458 | if (linklen && linkname[linklen-1] == '/') {
459 | linklen--;
460 | linkname[linklen] = '\0';
461 | }
462 | if (!stat(pathname, &sta2)) {
463 | if (S_ISREG(sta2.st_mode)) {
464 | hash_t *file;
465 | char *cx;
466 | struct tm *tmdat;
467 | char datebuf[32];
468 | file = hash_get(filelist, fname);
469 | if (!file) {
470 | if (check_exclude(exclude,dirname2))
471 | continue;
472 | file = new_hash();
473 | cx = new_string(fname);
474 | hash_put(file, "rawname", cx);
475 | hash_put_escurl(file, "name", "nameurl", cx);
476 | hash_put_escxml(file, "namexml", cx);
477 | hash_put(file, "dir", new_string_esc(dirname));
478 | hash_put(file, "desc", " ");
479 | hash_put(filelist, cx, file);
480 | }
481 | hash_put(file, "islink", "1");
482 | hash_put(file, "islinkfile", "1");
483 | hash_put(file, "linkpath", new_string(linkname)); /* ### canonicalize */
484 | sprintf(datebuf, "%ld", (long)sta2.st_mtime);
485 | hash_put(file, "date", new_string(datebuf));
486 | tmdat = localtime(&sta2.st_mtime);
487 | sprintf(datebuf, "%02d-%s-%d",
488 | tmdat->tm_mday, monthlist[tmdat->tm_mon], tmdat->tm_year+1900);
489 | hash_put(file, "datestr", new_string(datebuf));
490 | }
491 | else if (S_ISDIR(sta2.st_mode)) {
492 | char targetname[MAXPATHLEN+1];
493 | int targetlen;
494 | char *cx, *cx2;
495 | hash_t *file;
496 | strcpy(targetname, dirname);
497 | targetlen = strlen(targetname);
498 | for (cx = linkname; *cx; ) {
499 | cx2 = strchr(cx, '/');
500 | if (!cx2) {
501 | cx2 = cx + strlen(cx);
502 | }
503 | if (cx2-cx == 1 && cx[0] == '.') {
504 | /* nothing */
505 | }
506 | else if (cx2-cx == 2 && cx[0] == '.' && cx[1] == '.') {
507 | if (targetlen)
508 | targetlen--;
509 | while (targetlen && targetname[targetlen] != '/')
510 | targetlen--;
511 | }
512 | else {
513 | targetname[targetlen] = '/';
514 | targetlen++;
515 | memcpy(targetname+targetlen, cx, sizeof(char) * (cx2-cx));
516 | targetlen += (cx2-cx);
517 | }
518 | if (*cx2 == '/')
519 | cx2++;
520 | cx = cx2;
521 | }
522 | targetname[targetlen] = '\0';
523 | if (targetname[0] == '/')
524 | continue;
525 | file = hash_get(filelist, fname);
526 | if (!file) {
527 | char tempname[MAXPATHLEN+1];
528 | sprintf(tempname, "Symlink to %s", targetname);
529 | file = new_hash();
530 | cx = new_string(fname);
531 | hash_put(file, "name", cx);
532 | hash_put_escxml(file, "namexml", cx);
533 | hash_put(file, "dir", new_string(dirname));
534 | hash_put(file, "desc", new_string(tempname));
535 | hash_put(filelist, cx, file);
536 | }
537 | hash_put(file, "islink", "1");
538 | hash_put(file, "islinkdir", "1");
539 | cx = new_string(targetname);
540 | hash_put(file, "linkdir", cx);
541 | cx = new_string(targetname);
542 | for (cx2 = cx; *cx2; cx2++)
543 | if (*cx2 == '/')
544 | *cx2 = 'X';
545 | hash_put(file, "xlinkdir", cx);
546 | }
547 | }
548 | }
549 | }
550 | else if (S_ISREG(sta.st_mode)) {
551 | /* regular file */
552 | hash_t *file;
553 | char *cx;
554 | struct tm *tmdat;
555 | char datebuf[32];
556 | if (!strcmp(fname, "Index"))
557 | continue;
558 | file = hash_get(filelist, fname);
559 | if (!file) {
560 | if (check_exclude(exclude,dirname2))
561 | continue;
562 | file = new_hash();
563 | cx = new_string(fname);
564 | hash_put(file, "rawname", cx);
565 | hash_put_escurl(file, "name", "nameurl", cx);
566 | hash_put_escxml(file, "namexml", cx);
567 | hash_put(file, "dir", new_string_esc(dirname));
568 | hash_put(file, "desc", " ");
569 | hash_put(filelist, cx, file);
570 | }
571 | sprintf(datebuf, "%ld", (long)sta.st_size);
572 | hash_put(file, "filesize", new_string(datebuf));
573 | sprintf(datebuf, "%ld", (long)sta.st_mtime);
574 | hash_put(file, "date", new_string(datebuf));
575 | tmdat = localtime(&sta.st_mtime);
576 | sprintf(datebuf, "%02d-%s-%d",
577 | tmdat->tm_mday, monthlist[tmdat->tm_mon], tmdat->tm_year+1900);
578 | hash_put(file, "datestr", new_string(datebuf));
579 | if (domd5)
580 | hash_put(file, "md5", new_string(md5(pathname)));
581 | }
582 | else if (S_ISDIR(sta.st_mode)) {
583 | /* directory */
584 | hash_t *dir2, *file;
585 | char *cx, *cx2, *cx3;
586 | dir2 = hash_get(dirlist, dirname2);
587 | if (!dir2) {
588 | dir2 = new_hash();
589 | cx = new_string(dirname2);
590 | hash_put(dir2, "dir", cx);
591 | hash_put(dirlist, cx, dir2);
592 | hash_put(dir2, "@files", new_hash());
593 | cx = new_string(dirname2);
594 | for (cx2=cx; *cx2; cx2++)
595 | if (*cx2 == '/')
596 | *cx2 = 'X';
597 | hash_put(dir2, "xdir", cx);
598 | add_dir_links(dir2, dirname2);
599 |
600 | cx = new_string(dirname2);
601 | for (cx2=cx, cx3=NULL; *cx2; cx2++)
602 | if (*cx2 == '/')
603 | cx3 = cx2;
604 | if (cx3) {
605 | *cx3 = '\0';
606 | hash_put(dir2, "parentdir", new_string(cx));
607 | for (cx2 = cx; *cx2; cx2++)
608 | if (*cx2 == '/')
609 | *cx2 = 'X';
610 | hash_put(dir2, "xparentdir", cx);
611 | }
612 | }
613 | file = hash_get(filelist, fname);
614 | if (file) {
615 | cx = new_string(dirname2);
616 | hash_put(file, "linkdir", cx);
617 | cx = new_string(dirname2);
618 | for (cx2 = cx; *cx2; cx2++)
619 | if (*cx2 == '/')
620 | *cx2 = 'X';
621 | hash_put(file, "xlinkdir", cx);
622 | }
623 | if (parentlist && parentdir) {
624 | hash_t *parentfile;
625 | char parentname[MAXPATHLEN];
626 | sprintf(parentname,"%s/%s",parentdir,fname);
627 | parentfile = hash_get(parentlist, parentname);
628 | if (parentfile) {
629 | cx = new_string(dirname2);
630 | hash_put(parentfile, "linkdir", cx);
631 | cx = new_string(dirname2);
632 | for (cx2 = cx; *cx2; cx2++)
633 | if (*cx2 == '/')
634 | *cx2 = 'X';
635 | hash_put(parentfile, "xlinkdir", cx);
636 | }
637 | }
638 | scan_directory(dirlist, treedir, dirname2, filelist, fname, exclude, domd5);
639 | }
640 | }
641 |
642 | closedir(udir);
643 | }
644 |
645 | static int subdir_thunk(char *id, void *dirptr, void *rock)
646 | {
647 | contextsubdir_t *con = rock;
648 | hash_t *dir = dirptr;
649 | hash_t *filelist;
650 | int len;
651 | contextsubdire_t conm;
652 | char numbuf[16];
653 |
654 | filelist = hash_get(dir, "@files");
655 | if (filelist) {
656 | len = hash_length(filelist);
657 | if (len) {
658 | sprintf(numbuf, "%d", len);
659 | hash_put(dir, "count", new_string(numbuf));
660 | }
661 | }
662 |
663 | conm.con = con;
664 | conm.dir = dir;
665 | conm.dirname = id;
666 | conm.subdirlist = new_hash();
667 |
668 | hash_iterate(con->dirlist, &subdirel_thunk, &conm);
669 |
670 | hash_put(dir, "@subdirs", conm.subdirlist);
671 | len = hash_length(conm.subdirlist);
672 | if (len) {
673 | sprintf(numbuf, "%d", len);
674 | hash_put(dir, "subdircount", new_string(numbuf));
675 | }
676 | return FALSE;
677 | }
678 |
679 | static int subdirel_thunk(char *id, void *dirptr, void *rock)
680 | {
681 | contextsubdire_t *con = rock;
682 | hash_t *dir = dirptr;
683 | int idlen = strlen(con->dirname);
684 |
685 | if (!strncmp(con->dirname, id, idlen)
686 | && id[idlen] == '/'
687 | && !strchr(id+idlen+1, '/')) {
688 | hash_put(con->subdirlist, id, dir);
689 | }
690 | return FALSE;
691 | }
692 |
693 | static void tabsub(char *buf)
694 | {
695 | char buf2[BUFSIZE+1];
696 | char *cx, *cx2;
697 | int len2 = 0, count = 0;
698 |
699 | for (cx=buf, cx2=buf2; *cx; cx++) {
700 | if (*cx == '\t') {
701 | count++;
702 | do {
703 | *cx2++ = ' ';
704 | len2++;
705 | } while ((len2 & 8) != 0);
706 | }
707 | else {
708 | *cx2++ = *cx;
709 | len2++;
710 | }
711 | }
712 | *cx2 = '\0';
713 |
714 | if (count) {
715 | strcpy(buf, buf2);
716 | }
717 | }
718 |
719 | static int bracket_count(char* buf)
720 | {
721 | int count = 0;
722 |
723 | while (*buf != 0)
724 | {
725 | if ((*buf == '[') || (*buf == '('))
726 | count++;
727 | if ((*buf == ']') || (*buf == ')'))
728 | count--;
729 | buf++;
730 | }
731 |
732 | return count;
733 | }
734 |
735 |
--------------------------------------------------------------------------------