📄 qadm.c
字号:
/************************************************************************************************* * CGI script for administration of database files * Copyright (C) 2000-2003 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/#include <depot.h>#include <curia.h>#include <cabin.h>#include <villa.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdarg.h>#include <time.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#undef TRUE#define TRUE 1 /* boolean true */#undef FALSE#define FALSE 0 /* boolean false */#define CONFFILE "qadm.conf" /* name of the configuration file */#define DEFENC "US-ASCII" /* default encoding */#define DEFLANG "en" /* default language */#define DEFTITLE "QDBM on WWW" /* default title */#define DEFDBDIR "qadmdb" /* directory containing database files */#define RDATAMAX 262144 /* max size of data to read */#define DBNAMEMAX 128 /* max size of the name of a database */#define PATHBUFSIZ 1024 /* size of a buffer for path string */#define TSTRBUFSIZ 256 /* size of a buffer for time string */enum { ACTNONE, ACTDBDOWN, ACTDBCREATE, ACTDBREMOVE, ACTRECLIST, ACTRECPUTOVER, ACTRECPUTKEEP, ACTRECPUTCAT, ACTRECPUTDUP, ACTRECOUTONE, ACTRECOUTLIST};enum { DBTDEPOT, DBTCURIA, DBTVILLA, DBTERROR};/* global variables */const char *scriptname; /* name of the script */const char *enc; /* encoding of the page */const char *lang; /* language of the page */const char *title; /* title of the page */int keychop; /* whether to chop keys */int valchop; /* whether to chop values *//* function prototypes */int main(int argc, char **argv);int fwmatch(const char *str, const char *key);const char *skiplabel(const char *str);CBMAP *getparams(void);char *getpathinfo(void);void senderror(int code, const char *tag, const char *message);void dodbdown(const char *dbname);void dorecdown(const char *dbname, const char *tkey);void htmlprintf(const char *format, ...);void printmime(void);void printdecl(void);void printhead(void);const char *getdbattrs(const char *dbname, int *dbtp, int *rnump, int *fsizp, time_t *mtp);const char *dbtstr(int dbt);const char *timestr(time_t t);void dodblist();void dodbcreate(const char *dbname, int dbt);void dodbremove(const char *dbname, int sure);void doreclist(const char *dbname, int act, const char *key, const char *val, int sure);void strchop(char *str);void updatedepot(const char *dbname, int act, const char *key, const char *val);void updatecuria(const char *dbname, int act, const char *key, const char *val);void updatevilla(const char *dbname, int act, const char *key, const char *val);void depotreclist(const char *dbname);void curiareclist(const char *dbname);void villareclist(const char *dbname);/* main routine */int main(int argc, char **argv){ CBMAP *params; CBLIST *lines; const char *tmp, *dbdir, *dbname, *key, *val; char *pinfo, *tkey; int i, act, sure, dbt; /* set configurations */ scriptname = argv[0]; if((tmp = getenv("SCRIPT_NAME")) != NULL) scriptname = tmp; enc = NULL; lang = NULL; title = NULL; dbdir = NULL; keychop = FALSE; valchop = FALSE; if((lines = cbreadlines(CONFFILE)) != NULL){ for(i = 0; i < cblistnum(lines); i++){ tmp = cblistval(lines, i, NULL); if(fwmatch(tmp, "encoding:")){ enc = skiplabel(tmp); } else if(fwmatch(tmp, "lang:")){ lang = skiplabel(tmp); } else if(fwmatch(tmp, "title:")){ title = skiplabel(tmp); } else if(fwmatch(tmp, "dbdir:")){ dbdir = skiplabel(tmp); } else if(fwmatch(tmp, "keychop:")){ if(!strcmp(skiplabel(tmp), "true")) keychop = TRUE; } else if(fwmatch(tmp, "valchop:")){ if(!strcmp(skiplabel(tmp), "true")) valchop = TRUE; } } } if(!enc) enc = DEFENC; if(!lang) lang = DEFLANG; if(!title) title = DEFTITLE; if(!dbdir) dbdir = DEFDBDIR; /* read parameters */ dbname = NULL; act = ACTNONE; sure = FALSE; dbt = DBTERROR; key = NULL; val = NULL; params = getparams(); if((tmp = cbmapget(params, "act", -1, NULL)) != NULL) act = atoi(tmp); if((tmp = cbmapget(params, "sure", -1, NULL)) != NULL) sure = atoi(tmp); if((tmp = cbmapget(params, "dbname", -1, NULL)) != NULL) dbname = tmp; if((tmp = cbmapget(params, "dbt", -1, NULL)) != NULL) dbt = atoi(tmp); if((tmp = cbmapget(params, "key", -1, NULL)) != NULL) key = tmp; if((tmp = cbmapget(params, "val", -1, NULL)) != NULL) val = tmp; if(dbname && strlen(dbname) > DBNAMEMAX) dbname = NULL; pinfo = getpathinfo(); /* show page or send data */ if(chdir(dbdir) == -1){ senderror(500, "Internal Server Error", "Could not change the current directory."); } else if(act == ACTDBDOWN){ dodbdown(dbname); } else if(pinfo && (tkey = strchr(pinfo + 1, '/')) != NULL){ dbname = pinfo + 1; *tkey = '\0'; tkey++; dorecdown(dbname, tkey); } else { printmime(); printdecl(); htmlprintf("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"%s\" lang=\"%s\">\n", lang, lang); printhead(); htmlprintf("<body>\n"); if(act == ACTNONE){ htmlprintf("<h1>%@</h1>\n", title); } else { htmlprintf("<div class=\"note\"><a href=\"%s\">[BACK]</a></div>\n", scriptname); } htmlprintf("<hr />\n"); switch(act){ case ACTDBCREATE: dodbcreate(dbname, dbt); break; case ACTDBREMOVE: dodbremove(dbname, sure); break; case ACTRECLIST: case ACTRECPUTOVER: case ACTRECPUTKEEP: case ACTRECPUTCAT: case ACTRECPUTDUP: case ACTRECOUTONE: case ACTRECOUTLIST: doreclist(dbname, act, key, val, sure); break; default: dodblist(); break; } htmlprintf("<hr />\n"); if(act == ACTNONE) htmlprintf("<div class=\"note\">Powered by QDBM %@.</div>\n", dpversion); htmlprintf("</body>\n"); htmlprintf("</html>\n"); } /* release resources */ cbmapclose(params); if(lines) cblistclose(lines); return 0;}/* forward matching */int fwmatch(const char *str, const char *key){ int len, i; len = strlen(key); for(i = 0; i < len; i++){ if(str[i] != key[i] || str[i] == '\0') return FALSE; } return TRUE;}/* skip the label of a line */const char *skiplabel(const char *str){ if(!(str = strchr(str, ':'))) return str; str++; while(*str != '\0' && (*str == ' ' || *str == '\t')){ str++; } return str;}/* get a map of the CGI parameters */CBMAP *getparams(void){ CBMAP *params; CBLIST *pairs; char *rbuf, *buf, *key, *val, *dkey, *dval; const char *tmp; int i, len, c; params = cbmapopen(); rbuf = NULL; buf = NULL; if((tmp = getenv("CONTENT_LENGTH")) != NULL && (len = atoi(tmp)) > 0 && len <= RDATAMAX){ rbuf = malloc(len + 1); for(i = 0; i < len && (c = getchar()) != EOF; i++){ rbuf[i] = c; } rbuf[i] = '\0'; if(i == len) buf = rbuf; } else { buf = getenv("QUERY_STRING"); } if(buf != NULL){ buf = cbmemdup(buf, -1); pairs = cbsplit(buf, -1, "&"); for(i = 0; i < cblistnum(pairs); i++){ key = cbmemdup(cblistval(pairs, i, NULL), -1); if((val = strchr(key, '=')) != NULL){ *(val++) = '\0'; dkey = cburldecode(key, NULL); dval = cburldecode(val, NULL); cbmapput(params, dkey, -1, dval, -1, FALSE); free(dval); free(dkey); } free(key); } cblistclose(pairs); free(buf); } free(rbuf); return params;}/* get a string for PATH_INFO */char *getpathinfo(void){ const char *tmp; if((tmp = getenv("PATH_INFO")) != NULL){ return cburldecode(tmp, NULL); } return NULL;}/* send error status */void senderror(int code, const char *tag, const char *message){ printf("Status: %d %s\r\n", code, tag); printf("Content-Type: text/plain; charset=US-ASCII\r\n"); printf("\r\n"); printf("%s\n", message);}/* send a database */void dodbdown(const char *dbname){ FILE *IN; int c; if(!dbname || dbname[0] == '/' || strstr(dbname, "..") || !(IN = fopen(dbname, "rb"))){ senderror(404, "File Not Found", "The database file was not found."); } else { printf("Content-Type: application/x-qdbm\r\n"); printf("\r\n"); while((c = fgetc(IN)) != EOF){ putchar(c); } fclose(IN); }}/* send the value of a record */void dorecdown(const char *dbname, const char *tkey){ char vlpath[PATHBUFSIZ], crpath[PATHBUFSIZ], dppath[PATHBUFSIZ], *vbuf; int vsiz; DEPOT *depot; CURIA *curia; VILLA *villa; vbuf = NULL; vsiz = 0; sprintf(vlpath, "%s.vl", dbname); sprintf(crpath, "%s.cr", dbname); sprintf(dppath, "%s.dp", dbname); if((villa = vlopen(vlpath, VL_OREADER, VL_CMPLEX)) != NULL){ vbuf = vlget(villa, tkey, -1, &vsiz); vlclose(villa); } else if((curia = cropen(crpath, CR_OREADER, -1, -1)) != NULL){ vbuf = crget(curia, tkey, -1, 0, -1, &vsiz); crclose(curia); } else if((depot = dpopen(dppath, DP_OREADER, -1)) != NULL){ vbuf = dpget(depot, tkey, -1, 0, -1, &vsiz); dpclose(depot); } if(vbuf){ printf("Content-Type: text/plain; charset=%s\r\n", enc); printf("Content-Length: %d\r\n", vsiz); printf("\r\n"); printf("%s", vbuf); free(vbuf); } else { senderror(404, "Record Not Found", "There is no corresponding record."); }}/* HTML-oriented printf */void htmlprintf(const char *format, ...){ va_list ap; char *tmp; unsigned char c; va_start(ap, format); while(*format != '\0'){ if(*format == '%'){ format++; switch(*format){ case 's': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; printf("%s", tmp); break; case 'd': printf("%d", va_arg(ap, int)); break; case '@': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ switch(*tmp){ case '&': printf("&"); break; case '<': printf("<"); break; case '>': printf(">"); break; case '"': printf("""); break; default: putchar(*tmp); break; } tmp++; } break; case '?': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ c = *(unsigned char *)tmp; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ putchar(c); } else if(c == ' '){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -