/* ggzip.c -- unzipping for gretl databases using zlib routines. Output to basic stream or HTML page. Allin Cottrell (cottrell@wfu.edu) December, 2000 */ #include #include #include #include #include #include "server.h" #include #include #include #include #define MAXLEN 255 #define DESCRIP 64 #define PATHSEP '/' #define INFOLEN 100 #define LISTING 255 #define NFILES 20 #define FLEN 48 /* minimum gretl version needed for handling output of a database codebook by the server */ #define CB_MIN_VERSION 104 typedef float dbnumber; const char *cgi = "http://www.ecn.wfu.edu/gretl/cgi-bin/gretldata.cgi"; const char *dbsrc[] = { "Bank of Japan", "St Louis Fed", "Federal Reserve Board", "Federal Housing Finance Board", "NBER", "Barro", "Bureau of Economic Analysis", "European Central Bank", "Standard and Poors", "Bank of Canada", "eh.net", "UK National Statistics", "Banco de Espana", "Penn World Table", "DRI", "Dept of Commerce" }; const char *dburl[] = { "http://www.economagic.com/japan.htm", "http://www.economagic.com/fedstl.htm", "http://www.economagic.com/fedbog.htm", "http://www.economagic.com/fhfb.htm", "http://www.nber.org/databases/macrohistory/contents/", "http://www.nber.org/ftp/barro.lee/readme.txt", "http://www.economagic.com/beana.htm", "http://www.economagic.com/ecb.htm", "http://www.economagic.com/sp.htm", "http://www.economagic.com/bcan.htm", "http://eh.net/databases/labor/download.php", "http://www.statistics.gov.uk/statbase/tsdlistfiles.asp", "http://www.bde.es/infoest/htmls/downld.htm", "http://pwt.econ.upenn.edu/", "DRI", "Dept of Commerce" }; const char *month_name (int mon) { const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (mon < 1 || mon > 12) { return ""; } else { return months[mon - 1]; } } int is_ggzfile (const char *fname) { size_t n = strlen(fname); int ret = 0; if (n >= 4 && !strncmp(fname + n - 3, ".gz", 3)) { ret = 1; } return ret; } int is_gfnfile (const char *fname) { size_t n = strlen(fname); int ret = 0; if (n > 4 && !strncmp(fname + n - 4, ".gfn", 4)) { ret = 1; } return ret; } static void trim_descrip (char *descrip, size_t *n) { int i; descrip[DESCRIP-1] = 0; for (i=0; i\n" " "); printf("%s\n", title); puts("\n" "\n\n" "\n\n" "
"); printf("

%s

\n\n", title); if (gfn) { ; /* TODO */ } else { puts("

You can access these databases directly, using gretl " "version 0.40 or higher. Look under the menu item File, " "Browse databases, on database server.

\n"); } } static void files_table_top (int gfn) { const char *thstyle = ""; if (gfn) { printf("\n\n" "%sName" "%sAuthor" "%sVersion" "%sDate" "%sDescription\n", thstyle, thstyle, thstyle, thstyle, thstyle); } else { printf("
\n\n" "%sName" "%sSource" "%sDescription" "%sSize (bytes)" "%sDate prepared" "%s \n", thstyle, thstyle, thstyle, thstyle, thstyle, thstyle); } } static int printsrc (char *descrip) { int i = 0, n = sizeof dbsrc / sizeof *dbsrc; for (i=0; i

%s

", dburl[i], dbsrc[i]); } else { /* no actual URL is available */ printf("
", dburl[i]); } return i; } } printf(""); return -1; } char *delchar (int c, char *str) { int i, j; for (i=j=0; str[i] != 0; i++) { if (str[i] != c) { str[j++] = str[i]; } } str[j] = 0; return str; } static void ggz_html_print_info (gzFile fgz) { char descrip[DESCRIP], line[80], datestr[25]; char dbname[17]; char mon[4], day[3], yr[5]; int i, dbsize; int old_header = 0; gzgets(fgz, line, 80); if (sscanf(line, "%d%*s%*s%*s%*s%*s%16s", &dbsize, dbname) == 2) { old_header = 1; } else { sscanf(line, "%d %s %16s", &dbsize, datestr, dbname); } dbname[strlen(dbname) - 4] = 0; gzgets(fgz, line, 80); dbsize += atoi(line); if (old_header) { *datestr = 0; strncat(datestr, line + 9, 24); if (sscanf(datestr, "%*s %3s %3s %*s %4s", mon, day, yr) == 3) { sprintf(datestr, "%s %s, %s", mon, day, yr); } else { *datestr = 0; } } else { int cblen; *yr = *mon = *day = 0; strncat(yr, datestr, 4); strncat(mon, datestr + 4, 2); strncat(day, datestr + 6, 2); sprintf(datestr, "%s %s, %s", month_name(atoi(mon)), day, yr); gzgets(fgz, line, 80); if (sscanf(line, "%d", &cblen) == 1) { dbsize += cblen; } } gzseek(fgz, 100L, SEEK_SET); gzgets(fgz, line, DESCRIP); strcpy(descrip, line + 2); /* skip '# ' */ trim_descrip(descrip, NULL); printf(""); printf("", dbname); i = printsrc(descrip); if (i >= 0) { delchar('(', descrip); delchar(')', descrip); if (strcmp(dbsrc[i], "Barro")) { printf("", descrip + strlen(dbsrc[i])); } else { printf("", descrip); } } else { printf("", descrip); } printf("", dbsize); printf("", datestr); printf("\n", cgi, dbname); } /* Construct a string of the form: " 00:00:00 " where is 3-letter month, is 2 digits, and is 4-digit year; doesn't matter. */ char *numeric_date_to_ctime (char *tstr, const char *numdate) { int year, mon, day; char tmp[16]; *tmp = 0; strncat(tmp, numdate, 4); year = atoi(tmp); *tmp = 0; strncat(tmp, numdate + 4, 2); mon = atoi(tmp); *tmp = 0; strncat(tmp, numdate + 6, 2); day = atoi(tmp); sprintf(tstr, "Foo %s %02d 00:00:00 %d", month_name(mon), day, year); return tstr; } static void ggz_text_print_info (gzFile fgz) { char line[80], datestr[25]; char dbname[17]; int dbsize, old_header = 0; gzgets(fgz, line, 79); if (sscanf(line, "%d%*s%*s%*s%*s%*s%16s", &dbsize, dbname) == 2) { old_header = 1; fputs(line, stdout); } else { char indate[9]; if (sscanf(line, "%d %8s %16s", &dbsize, indate, dbname) != 3) { return; } numeric_date_to_ctime(datestr, indate); printf("%8d %s %15s\n", dbsize, datestr, dbname); } /* .bin file line */ gzgets(fgz, line, 79); if (old_header) { fputs(line, stdout); } else { char indate[9]; if (sscanf(line, "%d %8s %16s", &dbsize, indate, dbname) != 3) return; numeric_date_to_ctime(datestr, indate); printf("%8d %s %15s\n", dbsize, datestr, dbname); } /* database description line */ gzseek(fgz, 100L, SEEK_SET); gzgets(fgz, line, 79); fputs(line, stdout); } static int client_ok (const char *fname, int wfu_client) { if (!strncmp(fname, "cmini", 5) && !wfu_client) { return 0; } else { return 1; } } static int compare_names (const void *a, const void *b) { const char *na = *(char **) a; const char *nb = *(char **) b; return strcmp(na, nb); } static int file_is_ok (const char *fname, int gfn, int wfu) { if (gfn) { return is_gfnfile(fname); } else { return is_ggzfile(fname) && client_ok(fname, wfu); } } static void free_filenames (char **fnames, int n) { if (fnames != NULL && n > 0) { int i; for (i=0; id_name, gfn, wfu)) { nfiles++; if (nfiles >= nalloc) { fnames = allocate_filenames(fnames, ++blocks, &nalloc); if (fnames == NULL) { printf("Error: out of memory\n"); closedir(dir); return 0; } } strcpy(fnames[nfiles-1], dirent->d_name); } } closedir(dir); #if SDEBUG fprintf(fdb, "Found %d files\n", nfiles); #endif qsort(fnames, nfiles, sizeof *fnames, compare_names); if (html) { html_start(gfn); files_table_top(gfn); } /* cycle through the files and output their descriptions */ if (gfn) { emit_function_info(fnames, nfiles, version, html); } else { for (i=0; i\n\n\n\n"); } free_filenames(fnames, nalloc); return nfiles; } /* globals for streaming series */ static short nexp; static long nfrac; static int expo; static double frac; static char outbuf[16]; static size_t nfraclen = sizeof nfrac; static size_t nexplen = sizeof nexp; void ship_out_float (float x, gzFile fgz) { size_t i; frac = frexp(x, &expo); nexp = htons(expo); nfrac = htonl((long) (frac * 10e6)); if (fgz != NULL) { gzwrite(fgz, &nfrac, nfraclen); gzwrite(fgz, &nexp, nexplen); } else { memcpy(outbuf, &nfrac, nfraclen); for (i=0; i 0) { fwrite(gzbuf, 1, bgot, stdout); } else { break; } } fclose(fp); return 0; } /* otherwise we just send the database index info. note that we may be putting out HTML */ if (opt == TEXT) { content_line(TEXT); } fgz = gzopen(dbase, "rb"); if (fgz == NULL) { printf("Couldn't open database %s\n", dbase); return 1; } memset(gzbuf, 0, BUFSIZE); gzread(fgz, gzbuf, INFOLEN); /* first element in "info" is size of series listing in bytes */ idxlen = (size_t) atoi(gzbuf); for (i=0; i<1+idxlen/BUFSIZE; i++) { bytesleft = idxlen - BUFSIZE * i; if (bytesleft <= 0) { break; } zgot = gzread(fgz, gzbuf, (bytesleft > BUFSIZE)? BUFSIZE : bytesleft); for (j=0; j<(unsigned) zgot; j++) { putchar(gzbuf[j]); } } putchar('\0'); gzclose(fgz); return 0; } int nbo_send_file (const char *dbase) { size_t idxlen, bgot; char *tmpfile; char infobuf[INFOLEN], *gzbuf; gzFile fgz, ftmp; FILE *fp; struct stat fbuf; float x; tmpfile = tmpnam(NULL); if (tmpfile == NULL) return 1; ftmp = gzopen(tmpfile, "wb"); if (ftmp == Z_NULL) return 1; fgz = gzopen(dbase, "rb"); if (fgz == Z_NULL) return 1; memset(infobuf, 0, INFOLEN); gzread(fgz, infobuf, INFOLEN); idxlen = (size_t) atoi(infobuf); gzbuf = malloc(idxlen); if (gzbuf == NULL) { gzclose(ftmp); remove(tmpfile); return 1; } gzread(fgz, gzbuf, idxlen); /* new we've read all but the actual data -- ship out to gzipped tmp file */ gzwrite(ftmp, infobuf, INFOLEN); gzwrite(ftmp, gzbuf, idxlen); /* now read the data and convert */ memset(infobuf, 0, INFOLEN); while (gzread(fgz, infobuf, sizeof(float)) == sizeof(float)) { memcpy(&x, infobuf, sizeof(float)); ship_out_float(x, ftmp); } gzclose(fgz); gzclose(ftmp); if (stat(tmpfile, &fbuf)) { return 1; } /* now pump out the gzipped, reconstituted file */ printf("Content-Length: %lu\n\n", fbuf.st_size); fp = fopen(tmpfile, "rb"); if (fp == NULL) return 1; while (1) { if ((bgot = fread(gzbuf, 1, idxlen, fp)) > 0) { fwrite(gzbuf, 1, bgot, stdout); } else break; } fclose(fp); free(gzbuf); remove(tmpfile); return 0; }

%s

 
%s

%s

%s

%s

%d

%s

Series

" "