\n"
"
ftp.gnupg.org:%s
\n"
"
\n",
esc_title);
readme = fopen ("README", "r");
if (opt_readme && (readme = fopen ("README", "r")))
{
fputs ("
\n", stdout);
while (fgets (line, sizeof line, readme))
{
int no_lf = 0;
/* Eat up the rest of an incomplete line. */
if (!*line)
no_lf = 1;
else if (line[strlen (line)-1] != '\n')
{
no_lf = 1;
while ((c = getc (readme)) != EOF && c != '\n')
;
}
/* Replace empty lines with a leading doc by an empty
* line. These lines are used on FTP servers to avoid
* problems with broken FTP cleints. */
if (*line == '.')
{
for (p=line+1; (*p == ' ' || *p == '\t' || *p == '\n'); p++)
;
if (!*p)
{
putchar ('\n');
*line = 0;
}
}
if (*line)
fputs (html_escape_detect_link (line), stdout);
if (no_lf)
putchar ('\n');
}
fputs ("
\n", stdout);
fclose (readme);
}
fputs ("
\n", stdout);
}
else
{
printf ("\n"
"\n"
"
Index of %s\n"
"\n"
"\n"
"
Index of %s
\n"
"
\n",
esc_title, esc_title);
}
}
static void
print_footer (void)
{
if (!opt_html)
return;
if (opt_gpgweb)
{
fputs ("\n"
"\n"
"\n"
"\n"
"\n"
"\n", stdout);
}
else
{
printf ("
\n"
"\n"
"\n");
}
}
/* Print COUNT directories from the array SORTED.
* Note: This function assumes that the CWD is the listed directory. */
static void
print_dirs (finfo_t *sorted, int count, int at_root)
{
int idx;
finfo_t fi;
int any = 0;
char *title = NULL;
for (idx=0; idx < count; idx++)
{
fi = sorted[idx];
if (!fi->is_dir)
continue;
if (!any && opt_html)
{
any = 1;
if (opt_gpgweb)
{
fputs ("
Directories
\n"
"
\n"
"
\n", stdout);
if (!at_root)
fputs (" | "
""
"Parent Directory |
\n", stdout);
}
else
{
fputs ("  | "
"Directories |
\n",
stdout);
if (!at_root)
fputs (""
"Parent Directory |
\n", stdout);
}
}
free (title);
title = NULL;
if (opt_gpgweb)
{
char *fname;
FILE *fp;
fname = xstrconcat (fi->name, "/", ".title", NULL);
fp = fopen (fname, "r");
free (fname);
if (fp)
{
char line[200];
if (fgets (line, sizeof line, fp) && *line)
{
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = 0;
title = xstrdup (html_escape (line));
}
fclose (fp);
}
}
if (opt_html)
{
if (opt_gpgweb)
printf (" | "
"%s | ",
html_escape_href (fi->name), html_escape (fi->name));
else
printf ("
%s | ",
html_escape_href (fi->name), html_escape (fi->name));
if (title)
printf ("%s | ", title);
fputs ("
\n", stdout);
}
else
printf ("D %s\n", fi->name);
}
if (any && opt_gpgweb)
{
fputs ("
\n"
"
\n\n", stdout);
}
else if (opt_gpgweb && !at_root)
{
/* !any - need to print an UP link */
fputs ("
\n", stdout);
}
free (title);
}
/* Print COUNT files from the array SORTED. */
static void
print_files (finfo_t *sorted, int count)
{
int idx;
finfo_t fi;
int any = 0;
for (idx=0; idx < count; idx++)
{
fi = sorted[idx];
if (!fi->is_reg)
continue;
if (!any && opt_html)
{
any = 1;
if (opt_gpgweb)
{
fputs ("
Files
\n"
"
\n"
"
\n", stdout);
}
else
fputs ("Files |
\n",
stdout);
}
if (opt_gpgweb)
printf (" | "
"%s | "
"%s | %s |
\n",
strstr (fi->name, ".sig")? "document":
strstr (fi->name, ".tar")? "tar" : "document",
html_escape_href (fi->name), html_escape (fi->name),
format_time (fi->mtime), format_size (fi->size));
else if (opt_html)
printf ("%s | "
"%s | %s |
\n",
html_escape_href (fi->name), html_escape (fi->name),
format_time (fi->mtime), format_size (fi->size));
else
printf ("F %s\n", fi->name);
}
if (any && opt_gpgweb)
{
fputs ("
\n"
"
\n\n", stdout);
}
}
/* Scan DIRECTORY and print an index.
* FIXME: This does a chdir and does not preserve the old PWD.
* The fix is to build the full filename beofre stat'ing.
*/
static void
scan_directory (const char *directory, const char *title)
{
DIR *dir;
struct dirent *dentry;
finfo_t fi;
finfo_t finfo = NULL;
finfo_t *sorted;
int count = 0;
int idx;
size_t len;
strlist_t sl;
int at_root = 0;
if (opt_gpgweb)
{
if (!strcmp (title, "/"))
at_root = 1;
}
else if (!strcmp (directory, "/"))
at_root = 1;
dir = opendir (directory);
if (!dir)
{
err ("can't open directory '%s': %s\n", directory, strerror (errno));
return;
}
while (errno=0,(dentry = readdir (dir)))
{
if (*dentry->d_name == '.')
continue; /* Skip self, parent, and hidden directories. */
len = strlen (dentry->d_name);
if (!len)
continue; /* Empty filenames should actually not exist. */
if (dentry->d_name[len-1] == '~')
continue; /* Skip backup files. */
for (sl = opt_exclude; sl; sl = sl->next)
if (!strcmp (sl->d, dentry->d_name))
break;
if (sl)
continue; /* Skip excluded names. */
fi = xcalloc (1, sizeof *fi + strlen (dentry->d_name));
strcpy (fi->name, dentry->d_name);
fi->next = finfo;
finfo = fi;
count++;
}
if (errno)
die ("error reading directory '%s': %s\n", directory, strerror (errno));
closedir (dir);
sorted = xcalloc (count, sizeof *sorted);
for (fi=finfo, idx=0; fi; fi = fi->next)
sorted[idx++] = fi;
inf ("directory '%s' has %d files\n", directory, count);
qsort (sorted, count, sizeof *sorted, sort_finfo);
if (chdir (directory))
die ("cannot chdir to '%s': %s\n", directory, strerror (errno));
for (idx=0; idx < count; idx++)
{
struct stat sb;
fi = sorted[idx];
if (stat (fi->name, &sb))
{
err ("cannot stat '%s': %s\n", fi->name, strerror (errno));
continue;
}
fi->is_dir = !!S_ISDIR(sb.st_mode);
fi->is_reg = !!S_ISREG(sb.st_mode);
fi->size = fi->is_reg? sb.st_size : 0;
fi->mtime = sb.st_mtime;
}
print_header (title);
if (opt_files_first)
{
print_files (sorted, count);
print_dirs (sorted, count, at_root);
}
else
{
print_dirs (sorted, count, at_root);
print_files (sorted, count);
}
print_footer ();
/* We create the index file in the current directory. */
if (opt_index)
{
FILE *indexfp = fopen (opt_index, "w");
if (!indexfp)
die ("error creating '%s' for '%s': %s\n",
opt_index, directory, strerror (errno));
for (idx=0; idx < count; idx++)
{
fi = sorted[idx];
fprintf (indexfp, "%s:%c:%llu:%lu:\n",
percent_escape (fi->name),
fi->is_dir? 'd':
fi->is_reg? 'r': '?',
fi->size,
(unsigned long)fi->mtime);
}
if (ferror (indexfp))
die ("error writing '%s' for '%s': %s\n",
opt_index, directory, strerror (errno));
/* Fixme: Check for close errors. */
fclose (indexfp);
}
free (sorted);
while ((fi = finfo))
{
fi = finfo->next;
free (finfo);
finfo = fi;
}
}
int
main (int argc, char **argv)
{
int last_argc = -1;
strlist_t sl;
if (argc < 1)
die ("Hey, read up on how to use exec(2)\n");
argv++; argc--;
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--version"))
{
fputs (PGMNAME " " VERSION "\n"
"Copyright (C) 2017 g10 Code GmbH\n"
"License GPLv3+: GNU GPL version 3 or later"
"
\n"
"This is free software: you are free to change"
" and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n",
stdout);
exit (0);
}
else if (!strcmp (*argv, "--help"))
{
fputs ("usage: " PGMNAME " [options] directory [title]\n"
"Print an index for an FTP directory.\n\n"
"Options:\n"
" --version print program version\n"
" --verbose verbose diagnostics\n"
" --debug flyswatter\n"
" --reverse reverse sort order\n"
" --reverse-ver reverse only the version number order\n"
" --files-first print files before directories\n"
" --html output HTML\n"
" --gpgweb output HTML as used at gnupg.org\n"
" --readme include README file\n"
" --index FILE create index FILE\n"
" --exclude NAME ignore file NAME\n"
, stdout);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
opt_verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
opt_debug++;
argc--; argv++;
}
else if (!strcmp (*argv, "--reverse"))
{
opt_reverse = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--reverse-ver"))
{
opt_reverse_ver = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--files-first"))
{
opt_files_first = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--readme"))
{
opt_readme = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--html"))
{
opt_html = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--index"))
{
argc--; argv++;
if (!argc || !**argv)
die ("argument missing for option '%s'\n", argv[-1]);
opt_index = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--gpgweb"))
{
opt_gpgweb = opt_html = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--exclude"))
{
argc--; argv++;
if (!argc || !**argv)
die ("argument missing for option '%s'\n", argv[-1]);
sl = xmalloc (sizeof *sl + strlen (*argv));
strcpy (sl->d, *argv);
sl->next = opt_exclude;
opt_exclude = sl;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
die ("unknown option '%s' (use --help)\n", *argv);
}
if (argc < 1 || argc > 2)
die ("usage: " PGMNAME " [options] directory [title]\n");
scan_directory (argv[0], argv[1]? argv[1]:argv[0]);
return 0;
}
/*
Local Variables:
compile-command: "cc -Wall -g -o ftp-indexer ftp-indexer.c"
End:
*/
diff --git a/web/swdb.mac b/web/swdb.mac
index b7ecd28..57f0874 100644
--- a/web/swdb.mac
+++ b/web/swdb.mac
@@ -1,218 +1,218 @@
# Version information
# Please run make in this directory after changing this file.
#
# Primary FTP server base directory
#
#+macro: ftp_base ftp://ftp.gnupg.org/gcrypt
#+macro: ftp_loc_base /ftp/gcrypt
#
# GnuPG-2.2
#
#+macro: gnupg22_ver 2.2.11
#+macro: gnupg22_date 2018-11-06
#+macro: gnupg22_size 6496k
#+macro: gnupg22_sha1 c762d300c6c5616c14abff1cfaa099baa5fcbd2c
#+macro: gnupg22_sha2 496c3e123ef53f35436ddccca58e82acaa901ca4e21174e77386c0cea0c49cd9
#+macro: gnupg22_branch STABLE-BRANCH-2-2
#+macro: gnupg22_w32_ver 2.2.11_20181106
#+macro: gnupg22_w32_date 2018-11-06
#+macro: gnupg22_w32_size 3928k
#+macro: gnupg22_w32_sha1 d1b1ba1bcf433cd1accf22772600f8a5186e156c
#+macro: gnupg22_w32_sha2 1e3fe08215b34f1ba71e7fb7856151db9167478cb9e8f21140801d776799bdfe
#
# GnuPG 2.0 (end-of-life)
#
#+macro: gnupg20_ver 2.0.31
#+macro: gnupg20_date 2017-12-29
#+macro: gnupg20_size 4324k
#+macro: gnupg20_sha1 a7d5021a6a39dd67942e00a1239e37063edb00f0
#+macro: gnupg20_sha2 095558cfbba52fba582963e97b0c016889570b4712d6b871abeef2cf93e62293
#+macro: gnupg20_branch STABLE-BRANCH-2-0
#
# GnuPG-1
#
#+macro: gnupg1_ver 1.4.23
#+macro: gnupg1_date 2018-06-11
#+macro: gnupg1_size 3661k
#+macro: gnupg1_sha1 13747486ed5ff707f796f34f50f4c3085c3a6875
#+macro: gnupg1_sha2 c9462f17e651b6507848c08c430c791287cd75491f8b5a8b50c6ed46b12678ba
#
#+macro: gnupg1_w32cli_ver 1.4.23
#+macro: gnupg1_w32cli_size 2376k
#+macro: gnupg1_w32cli_sha1 d4c9962179d36a140be72c34f34e557b56c975b5
#
# Gpg4win
#
#+macro: gpg4win_ver 3.1.5
#+macro: gpg4win_date 2018-11-13
#+macro: gpg4win_src_size 5301k
#+macro: gpg4win_src_sha1 7bd3343f76a1d7df2d1d565cf3d1ede959286a4d
#+macro: gpg4win_src_sha2 456143b0542557701a5dbb96240e818573b00afadeb9e7eee194343ff4b839e4
#+macro: gpg4win_exe_size 27820k
#+macro: gpg4win_exe_sha1 675b2261029ba54486eac08c9ac0fe09c7f1626c
#+macro: gpg4win_exe_sha2 4749ab2d02d384abc2b0fd045c86380e6f840b540a2081e6c0f7d538a3397b23
#+macro: gpg4win_isrc_size 223311k
#+macro: gpg4win_isrc_sha1 7ff481557428ebc37fc91518375d6239540a7c74
#+macro: gpg4win_isrc_sha2 5ee57522b0da38e3f4ed80e3e6262d7fc6a557b52e7cd42ec32a01db6d1889f1
#
# GPA
#
#+macro: gpa_ver 0.10.0
#+macro: gpa_date 2018-10-16
#+macro: gpa_size 745k
#+macro: gpa_sha1 61475989acd12de8b7daacd906200e8b4f519c5a
#+macro: gpa_sha2 95dbabe75fa5c8dc47e3acf2df7a51cee096051e5a842b4c9b6d61e40a6177b1
#
# PINENTRY
#
#+macro: pinentry_ver 1.1.0
#+macro: pinentry_date 2017-12-03
#+macro: pinentry_size 456k
#+macro: pinentry_sha1 693bdf9f48dfb3e040d92f50b1bb464e268b9fb0
#+macro: pinentry_sha2 68076686fa724a290ea49cdf0d1c0c1500907d1b759a3bcbfbec0293e8f56570
#
# GPGME
#
#+macro: gpgme_ver 1.12.0
#+macro: gpgme_date 2018-10-08
#+macro: gpgme_size 1619k
#+macro: gpgme_sha1 6f1828fcd7de4366ca063e57f35e4ab24bc91baf
#+macro: gpgme_sha2 b4dc951c3743a60e2e120a77892e9e864fb936b2e58e7c77e8581f4d050e8cd8
#
# LIBGCRYPT
#
#+macro: libgcrypt_ver 1.8.4
#+macro: libgcrypt_date 2018-10-26
#+macro: libgcrypt_size 2920k
#+macro: libgcrypt_sha1 4a8ef9db6922f3a31992aca5640b4198a69b58fc
#+macro: libgcrypt_sha2 f638143a0672628fde0cad745e9b14deb85dffb175709cacc1f4fe24b93f2227
#
# LIBKSBA
#
#+macro: libksba_ver 1.3.5
#+macro: libksba_date 2016-08-22
#+macro: libksba_size 606k
#+macro: libksba_sha1 a98385734a0c3f5b713198e8d6e6e4aeb0b76fde
#+macro: libksba_sha2 41444fd7a6ff73a79ad9728f985e71c9ba8cd3e5e53358e70d5f066d35c1a340
#
# DirMngr (not any longer needed)
#
#+macro: dirmngr_ver 1.1.1
#+macro: dirmngr_date 2013-04-26
#+macro: dirmngr_size 554k
#+macro: dirmngr_sha1 e708d4aa5ce852f4de3f4b58f4e4f221f5e5c690
#
-# LIBGPG-ERROR
-#
-#+macro: libgpg_error_ver 1.32
-#+macro: libgpg_error_date 2018-07-12
-#+macro: libgpg_error_size 883k
-#+macro: libgpg_error_sha1 e310718c7737c816cb1313a2f3baf60fd6a6d5d3
-#+macro: libgpg_error_sha2 c345c5e73cc2332f8d50db84a2280abfb1d8f6d4f1858b9daa30404db44540ca
-#+macro: gpgrt_error_ver 1.32
-#+macro: gpgrt_error_date 2018-07-12
-#+macro: gpgrt_error_size 883k
-#+macro: gpgrt_error_sha1 e310718c7737c816cb1313a2f3baf60fd6a6d5d3
-#+macro: gpgrt_error_sha2 c345c5e73cc2332f8d50db84a2280abfb1d8f6d4f1858b9daa30404db44540ca
+# LIBGPG-ERROR (aka GPGRT)
+#
+#+macro: libgpg_error_ver 1.33
+#+macro: libgpg_error_date 2018-12-07
+#+macro: libgpg_error_size 896k
+#+macro: libgpg_error_sha1 bd40bf4cb6a0b725f5ea91b68d6ae5aeb387a750
+#+macro: libgpg_error_sha2 5d38826656e746c936e7742d9cde072b50baa3c4c49daa168a56813612bf03ff
+#+macro: gpgrt_ver 1.33
+#+macro: gpgrt_date 2018-12-07
+#+macro: gpgrt_size 896k
+#+macro: gpgrt_sha1 bd40bf4cb6a0b725f5ea91b68d6ae5aeb387a750
+#+macro: gpgrt_sha2 5d38826656e746c936e7742d9cde072b50baa3c4c49daa168a56813612bf03ff
#
# LIBASSUAN
#
#+macro: libassuan_ver 2.5.1
#+macro: libassuan_date 2017-12-07
#+macro: libassuan_size 551k
#+macro: libassuan_sha1 c8432695bf1daa914a92f51e911881ed93d50604
#+macro: libassuan_sha2 47f96c37b4f2aac289f0bc1bacfa8bd8b4b209a488d3d15e2229cb6cc9b26449
#
# NTBTLS
#
#+macro: ntbtls_ver 0.1.2
#+macro: ntbtls_date 2017-09-19
#+macro: ntbtls_size 334k
#+macro: ntbtls_sha1 05cf57cd8400b338b94bdce7287397c24315ac49
#+macro: ntbtls_sha2 8240db84e50c2351b19eb8064bdfd4d25e3c157d37875c62e335df237d7bdce7
#
# nPth
#
#+macro: npth_ver 1.6
#+macro: npth_date 2018-07-16
#+macro: npth_size 293k
#+macro: npth_sha1 f9d63e9747b027e4e404fe3c20c73c73719e1731
#+macro: npth_sha2 1393abd9adcf0762d34798dc34fdcf4d0d22a8410721e76f1e3afcd1daa4e2d1
#
# GpgEX
#
#+macro: gpgex_ver 1.0.6
#+macro: gpgex_date 2018-04-10
#+macro: gpgex_size 297k
#+macro: gpgex_sha1 443270219d542f97b6f124d2101ae8d803c6dbe2
#+macro: gpgex_sha2 d69898d1022400bd09bb684080edc95be554af736ae9c014df73543f34f7481b
#
# GpgOL
#
#+macro: gpgol_ver 2.3.2
#+macro: gpgol_date 2018-11-12
#+macro: gpgol_size 766k
#+macro: gpgol_sha1 b2d48f17b2cf20f6c55b98dbad1f14ac6e3adfc4
#+macro: gpgol_sha2 6c298c7a8787e0796a1984d3c1e948b55b9fff685dff3fe7e9d3012001b5b85f
#
# ADNS
#
#+macro: adns_ver 1.4-g10-7
#+macro: adns_date 2015-11-20
#+macro: adns_sha1 d2e089d98d3faed6cad009477cc0bc030b35c646
#
# zlib (mirrored at our server)
#
#+macro: zlib_ver 1.2.8
#+macro: zlib_sha1_gz a4d316c404ff54ca545ea71a27af7dbc29817088
#
# bzip2 (mirrored and stripped down version)
#
#+macro: bzip2_ver 1.0.6-g10
#+macro: bzip2_sha1_gz 6e38be3377340a21a1f13ff84b5e6adce97cd1d4
#
# SQLite (mirrored at our server)
#
#+macro: sqlite_ver 3120200
#+macro: sqlite_sha1_gz b43c2e7238e54c50b95fbbd85c48792f4f39af8c
# --- end of swdb.mac ---