/* Find a compression library/method given a name */ static int findmethod(struct XpkBuffer *xbuf, char *name) { unsigned int id; /* Try to use the first four letters as the ID */ if(!name || !*name) return XPKERR_BADPARAMS; else if((id=idfromname(name)) == USER_COOKIE) xbuf->xb_PackingMode=100; else if(!opensub(xbuf, id)) return xbuf->xb_Result; else xbuf->xb_PackingMode=xbuf->xb_SubInfo->xi_DefMode; /* note: invalid add-ons aren't checked here */ if(name[4] == '.') xbuf->xb_PackingMode=strtoul(name + 5, 0, 10); return 0; }
const char *issub(const char *dir, const char *subdir, const char *userhost) /* Returns (char *) to match if userhost is in the subscriber database */ /* dir, 0 otherwise. dir is a base directory for a list and may NOT */ /* be NULL */ /* NOTE: The returned pointer is NOT VALID after a subsequent call to issub!*/ { MYSQL_RES *result; MYSQL_ROW row; const char *ret; const char *table; unsigned long *lengths; unsigned int j; if ((ret = opensub(dir,subdir,&table))) { if (*ret) strerr_die2x(111,FATAL,ret); return std_issub(dir,subdir,userhost); } else { /* SQL version */ /* SELECT address FROM list WHERE address = 'userhost' AND hash */ /* BETWEEN 0 AND 52. Without the hash restriction, we'd make it */ /* even easier to defeat. Just faking sender to the list name would*/ /* work. Since sender checks for posts are bogus anyway, I don't */ /* know if it's worth the cost of the "WHERE ...". */ if (!stralloc_copys(&addr,userhost)) die_nomem(); j = byte_rchr(addr.s,addr.len,'@'); if (j == addr.len) return 0; case_lowerb(addr.s + j + 1,addr.len - j - 1); if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem(); if (!stralloc_cats(&line,table)) die_nomem(); if (!stralloc_cats(&line," WHERE address = '")) die_nomem(); if (!stralloc_ready("ed,2 * addr.len + 1)) die_nomem(); if (!stralloc_catb(&line,quoted.s, mysql_escape_string(quoted.s,userhost,addr.len))) die_nomem(); if (!stralloc_cats(&line,"'")) die_nomem(); if (mysql_real_query(mysql,line.s,line.len)) /* query */ strerr_die2x(111,FATAL,mysql_error(mysql)); if (!(result = mysql_use_result(mysql))) strerr_die2x(111,FATAL,mysql_error(mysql)); row = mysql_fetch_row(result); ret = (char *) 0; if (!row) { /* we need to return the actual address as other */ /* dbs may accept user-*@host, but we still want */ /* to make sure to send to e.g the correct moderator*/ /* address. */ if (!mysql_eof(result)) strerr_die2x(111,FATAL,mysql_error(mysql)); } else { if (!(lengths = mysql_fetch_lengths(result))) strerr_die2x(111,FATAL,mysql_error(mysql)); if (!stralloc_copyb(&line,row[0],lengths[0])) die_nomem(); if (!stralloc_0(&line)) die_nomem(); ret = line.s; while ((row = mysql_fetch_row(result))); /* maybe not necessary */ mysql_free_result(result); } return ret; } }
const char *logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done) /* creates an entry for message num and the list listno and code "done". */ /* Returns NULL on success, "" if dir/sql was not found, and the error */ /* string on error. NOTE: This routine does nothing for non-sql lists! */ { const char *table; const char *ret; PGresult *result; PGresult *result2; if ((ret = opensub(dir,0,&table))) { if (*ret) return ret; else return (char *) 0; /* no SQL => success */ } if (!stralloc_copys(&logline,"INSERT INTO ")) return ERR_NOMEM; if (!stralloc_cats(&logline,table)) return ERR_NOMEM; if (!stralloc_cats(&logline,"_mlog (msgnum,listno,subs,done) VALUES (")) return ERR_NOMEM; if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,num))) return ERR_NOMEM; if (!stralloc_cats(&logline,",")) return ERR_NOMEM; if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,listno))) return ERR_NOMEM; if (!stralloc_cats(&logline,",")) return ERR_NOMEM; if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,subs))) return ERR_NOMEM; if (!stralloc_cats(&logline,",")) return ERR_NOMEM; if (done < 0) { done = - done; if (!stralloc_append(&logline,"-")) return ERR_NOMEM; } if (!stralloc_catb(&logline,strnum,fmt_uint(strnum,done))) return ERR_NOMEM; if (!stralloc_append(&logline,")")) return ERR_NOMEM; if (!stralloc_0(&logline)) return ERR_NOMEM; result = PQexec(pgsql,logline.s); if(result==NULL) return (PQerrorMessage(pgsql)); if(PQresultStatus(result) != PGRES_COMMAND_OK) { /* Check if duplicate */ if (!stralloc_copys(&logline,"SELECT msgnum FROM ")) return ERR_NOMEM; if (!stralloc_cats(&logline,table)) return ERR_NOMEM; if (!stralloc_cats(&logline,"_mlog WHERE msgnum = ")) return ERR_NOMEM; if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,num))) return ERR_NOMEM; if (!stralloc_cats(&logline," AND listno = ")) return ERR_NOMEM; if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,listno))) return ERR_NOMEM; if (!stralloc_cats(&logline," AND done = ")) return ERR_NOMEM; if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,done))) return ERR_NOMEM; /* Query */ if (!stralloc_0(&logline)) return ERR_NOMEM; result2 = PQexec(pgsql,logline.s); if (result2 == NULL) return (PQerrorMessage(pgsql)); if (PQresultStatus(result2) != PGRES_TUPLES_OK) return (char *) (PQresultErrorMessage(result2)); /* No duplicate, return ERROR from first query */ if (PQntuples(result2)<1) return (char *) (PQresultErrorMessage(result)); PQclear(result2); } PQclear(result); return (char *) 0; }
void tagmsg(const char *dir, /* db base dir */ unsigned long msgnum, /* number of this message */ const char *seed, /* seed. NULL ok, but less entropy */ const char *action, /* to make it certain the cookie differs from*/ /* one used for a digest */ char *hashout, /* calculated hash goes here */ unsigned long bodysize, unsigned long chunk) /* This routine creates a cookie from num,seed and the */ /* list key and returns that cookie in hashout. The use of sender/num and */ /* first char of action is used to make cookie differ between messages, */ /* the key is the secret list key. The cookie will be inserted into */ /* table_cookie where table and other data is taken from dir/sql. We log */ /* arrival of the message (done=0). */ { PGresult *result; PGresult *result2; /* Need for dupicate check */ const char *table; const char *ret; std_tagmsg(msgnum,seed,action,hashout); if ((ret = opensub(dir,0,&table))) { if (*ret) strerr_die2x(111,FATAL,ret); return; /* no sql => success */ } else { if (chunk >= 53L) chunk = 0L; /* sanity */ /* INSERT INTO table_cookie (msgnum,cookie) VALUES (num,cookie) */ /* (we may have tried message before, but failed to complete, so */ /* ER_DUP_ENTRY is ok) */ if (!stralloc_copys(&line,"INSERT INTO ")) die_nomem(); if (!stralloc_cats(&line,table)) die_nomem(); if (!stralloc_cats(&line,"_cookie (msgnum,cookie,bodysize,chunk) VALUES (")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,msgnum))) die_nomem(); if (!stralloc_cats(&line,",'")) die_nomem(); if (!stralloc_catb(&line,hashout,COOKIE)) die_nomem(); if (!stralloc_cats(&line,"',")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,bodysize))) die_nomem(); if (!stralloc_cats(&line,",")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,chunk))) die_nomem(); if (!stralloc_cats(&line,")")) die_nomem(); if (!stralloc_0(&line)) die_nomem(); result = PQexec(pgsql,line.s); if (result == NULL) strerr_die2x(111,FATAL,PQerrorMessage(pgsql)); if (PQresultStatus(result) != PGRES_COMMAND_OK) { /* Possible tuplicate */ if (!stralloc_copys(&line,"SELECT msgnum FROM ")) die_nomem(); if (!stralloc_cats(&line,table)) die_nomem(); if (!stralloc_cats(&line,"_cookie WHERE msgnum = ")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,msgnum))) die_nomem(); /* Query */ if (!stralloc_0(&line)) die_nomem(); result2 = PQexec(pgsql,line.s); if (result2 == NULL) strerr_die2x(111,FATAL,PQerrorMessage(pgsql)); if (PQresultStatus(result2) != PGRES_TUPLES_OK) strerr_die2x(111,FATAL,PQresultErrorMessage(result2)); /* No duplicate, return ERROR from first query */ if (PQntuples(result2)<1) strerr_die2x(111,FATAL,PQresultErrorMessage(result)); PQclear(result2); } PQclear(result); if (! (ret = logmsg(dir,msgnum,0L,0L,1))) return; /* log done=1*/ if (*ret) strerr_die2x(111,FATAL,ret); } return; }