/* * Deliver digest messages */ void network_deliver_digest(SpoolControl *sc) { struct CitContext *CCC = CC; long len; char buf[SIZ]; char *pbuf; struct CtdlMessage *msg = NULL; long msglen; recptypes *valid; char bounce_to[256]; if (sc->Users[digestrecp] == NULL) return; msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); msg->cm_magic = CTDLMESSAGE_MAGIC; msg->cm_format_type = FMT_RFC822; msg->cm_anon_type = MES_NORMAL; CM_SetFieldLONG(msg, eTimestamp, time(NULL)); CM_SetField(msg, eAuthor, CCC->room.QRname, strlen(CCC->room.QRname)); len = snprintf(buf, sizeof buf, "[%s]", CCC->room.QRname); CM_SetField(msg, eMsgSubject, buf, len); CM_SetField(msg, erFc822Addr, SKEY(sc->Users[roommailalias])); CM_SetField(msg, eRecipient, SKEY(sc->Users[roommailalias])); /* Set the 'List-ID' header */ CM_SetField(msg, eListID, SKEY(sc->ListID)); /* * Go fetch the contents of the digest */ fseek(sc->digestfp, 0L, SEEK_END); msglen = ftell(sc->digestfp); pbuf = malloc(msglen + 1); fseek(sc->digestfp, 0L, SEEK_SET); fread(pbuf, (size_t)msglen, 1, sc->digestfp); pbuf[msglen] = '\0'; CM_SetAsField(msg, eMesageText, &pbuf, msglen); /* Now generate the delivery instructions */ /* Where do we want bounces and other noise to be heard? * Surely not the list members! */ snprintf(bounce_to, sizeof bounce_to, "room_aide@%s", config.c_fqdn); /* Now submit the message */ valid = validate_recipients(ChrPtr(sc->Users[digestrecp]), NULL, 0); if (valid != NULL) { valid->bounce_to = strdup(bounce_to); valid->envelope_from = strdup(bounce_to); CtdlSubmitMsg(msg, valid, NULL, 0); } CM_Free(msg); free_recipients(valid); }
time_t CheckIfAlreadySeen(const char *Facility, StrBuf *guid, time_t now, time_t antiexpire, eCheckType cType, long ccid, long ioid) { time_t InDBTimeStamp = 0; struct UseTable ut; struct cdbdata *cdbut; if (cType != eWrite) { SEEN_syslog(LOG_DEBUG, "Loading [%s]", ChrPtr(guid)); cdbut = cdb_fetch(CDB_USETABLE, SKEY(guid)); if ((cdbut != NULL) && (cdbut->ptr != NULL)) { memcpy(&ut, cdbut->ptr, ((cdbut->len > sizeof(struct UseTable)) ? sizeof(struct UseTable) : cdbut->len)); InDBTimeStamp = now - ut.ut_timestamp; if (InDBTimeStamp < antiexpire) { SEEN_syslog(LOG_DEBUG, "Found - Not expired %ld < %ld", InDBTimeStamp, antiexpire); cdb_free(cdbut); return InDBTimeStamp; } else { SEEN_syslog(LOG_DEBUG, "Found - Expired. %ld >= %ld", InDBTimeStamp, antiexpire); cdb_free(cdbut); } } else { if (cdbut) cdb_free(cdbut); SEENM_syslog(LOG_DEBUG, "not Found"); } if (cType == eCheckExist) return InDBTimeStamp; } memcpy(ut.ut_msgid, SKEY(guid)); ut.ut_timestamp = now; SEENM_syslog(LOG_DEBUG, "Saving new Timestamp"); /* rewrite the record anyway, to update the timestamp */ cdb_store(CDB_USETABLE, SKEY(guid), &ut, sizeof(struct UseTable) ); SEENM_syslog(LOG_DEBUG, "Done Saving"); return InDBTimeStamp; }
void network_process_participate(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { struct CtdlMessage *msg = NULL; int ok_to_participate = 0; StrBuf *Buf = NULL; recptypes *valid; /* * Process client-side list participations for this room */ if (sc->Users[participate] == NULL) return; msg = CM_Duplicate(omsg); /* Only send messages which originated on our own * Citadel network, otherwise we'll end up sending the * remote mailing list's messages back to it, which * is rude... */ ok_to_participate = 0; if (!CM_IsEmpty(msg, eNodeName)) { if (!strcasecmp(msg->cm_fields[eNodeName], config.c_nodename)) { ok_to_participate = 1; } Buf = NewStrBufPlain(CM_KEY(msg, eNodeName)); if (CtdlIsValidNode(NULL, NULL, Buf, sc->working_ignetcfg, sc->the_netmap) == 0) { ok_to_participate = 1; } } if (ok_to_participate) { /* Replace the Internet email address of the * actual author with the email address of the * room itself, so the remote listserv doesn't * reject us. */ CM_SetField(msg, erFc822Addr, SKEY(sc->Users[roommailalias])); valid = validate_recipients(ChrPtr(sc->Users[participate]) , NULL, 0); CM_SetField(msg, eRecipient, SKEY(sc->Users[roommailalias])); CtdlSubmitMsg(msg, valid, "", 0); free_recipients(valid); } FreeStrBuf(&Buf); CM_Free(msg); }
/* * A template has been requested */ void url_do_template(void) { const StrBuf *MimeType; const StrBuf *Tmpl = sbstr("template"); begin_burst(); MimeType = DoTemplate(SKEY(Tmpl), NULL, &NoCtx); http_transmit_thing(ChrPtr(MimeType), 0); }
/* * modify an existing node */ void display_edit_node(void) { WCTemplputParams SubTP; HashList *NodeConfig; const StrBuf *Index; void *vNode; const StrBuf *Tmpl; Index = sbstr("index"); if (Index == NULL) { AppendImportantMessage(_("Invalid Parameter"), -1); url_do_template(); return; } NodeConfig = load_netconf(NULL, &NoCtx); if (!GetHash(NodeConfig, ChrPtr(Index), StrLength(Index), &vNode) || (vNode == NULL)) { AppendImportantMessage(_("Invalid Parameter"), -1); url_do_template(); DeleteHash(&NodeConfig); return; } StackContext(NULL, &SubTP, vNode, CTX_NODECONF, 0, NULL); { begin_burst(); Tmpl = sbstr("template"); output_headers(1, 0, 0, 0, 1, 0); DoTemplate(SKEY(Tmpl), NULL, &SubTP); end_burst(); } UnStackContext(&SubTP); DeleteHash(&NodeConfig); }
OneQueItem *DeserializeQueueItem(StrBuf *RawQItem, long QueMsgID) { OneQueItem *Item; const char *pLine = NULL; StrBuf *Line; StrBuf *Token; void *v; Item = (OneQueItem*)malloc(sizeof(OneQueItem)); memset(Item, 0, sizeof(OneQueItem)); Item->Retry = SMTP_RETRY_INTERVAL; Item->MessageID = -1; Item->QueMsgID = QueMsgID; Token = NewStrBuf(); Line = NewStrBufPlain(NULL, 128); while (pLine != StrBufNOTNULL) { const char *pItemPart = NULL; void *vHandler; StrBufExtract_NextToken(Line, RawQItem, &pLine, '\n'); if (StrLength(Line) == 0) continue; StrBufExtract_NextToken(Token, Line, &pItemPart, '|'); if (GetHash(QItemHandlers, SKEY(Token), &vHandler)) { QItemHandlerStruct *HS; HS = (QItemHandlerStruct*) vHandler; HS->H(Item, Line, &pItemPart); } } FreeStrBuf(&Line); FreeStrBuf(&Token); if (Item->Retry >= MaxRetry) Item->FailNow = 1; pthread_mutex_lock(&ActiveQItemsLock); if (GetHash(ActiveQItems, LKEY(Item->MessageID), &v)) { /* WHOOPS. somebody else is already working on this. */ pthread_mutex_unlock(&ActiveQItemsLock); FreeQueItem(&Item); return NULL; } else { /* mark our claim on this. */ Put(ActiveQItems, LKEY(Item->MessageID), Item, HFreeQueItem); pthread_mutex_unlock(&ActiveQItemsLock); } return Item; }
void SortPregetMatter(HashList *Cals) { disp_cal *Cal; void *vCal; const char *Key; long KLen; IcalEnumMap *SortMap[10]; IcalEnumMap *Map; void *vSort; const char *Next = NULL; const StrBuf *SortVector; StrBuf *SortBy; int i = 0; HashPos *It; SortVector = SBSTR("ICALSortVec"); if (SortVector == NULL) return; for (i = 0; i < 10; i++) SortMap[i] = NULL; SortBy = NewStrBuf(); while (StrBufExtract_NextToken(SortBy, SortVector, &Next, ':') > 0) { GetHash(IcalComponentMap, SKEY(SortBy), &vSort); Map = (IcalEnumMap*) vSort; SortMap[i] = Map; i++; if (i > 9) break; } if (i == 0) return; switch (SortMap[i - 1]->map) { /* case */ default: break; } It = GetNewHashPos(Cals, 0); while (GetNextHashPos(Cals, It, &KLen, &Key, &vCal)) { i = 0; Cal = (disp_cal*) vCal; Cal->Status = icalcomponent_get_status(Cal->cal); Cal->SortBy = Cal->cal; while ((SortMap[i] != NULL) && (Cal->SortBy != NULL)) { /****Cal->SortBy = icalcomponent_get_first_property(Cal->SortBy, SortMap[i++]->map); */ } } }
void network_process_list(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { struct CtdlMessage *msg = NULL; /* * Process mailing list recipients */ if (sc->Users[listrecp] == NULL) return; /* create our own copy of the message. * We're going to need to modify it * in order to insert the [list name] in it, etc. */ msg = CM_Duplicate(omsg); CM_SetField(msg, eReplyTo, SKEY(sc->Users[roommailalias])); /* if there is no other recipient, Set the recipient * of the list message to the email address of the * room itself. */ if (CM_IsEmpty(msg, eRecipient)) { CM_SetField(msg, eRecipient, SKEY(sc->Users[roommailalias])); } /* Set the 'List-ID' header */ CM_SetField(msg, eListID, SKEY(sc->ListID)); /* Prepend "[List name]" to the subject */ ListCalculateSubject(msg); /* Handle delivery */ network_deliver_list(msg, sc, CC->room.QRname); CM_Free(msg); }
eNextState FinalizePOP3AggrRun(AsyncIO *IO) { HashPos *It; pop3aggr *cpptr = (pop3aggr *)IO->Data; EVP3C_syslog(LOG_INFO, "%s@%s: fetched %ld new of %d messages in %fs. bye.", ChrPtr(cpptr->pop3user), ChrPtr(cpptr->Host), cpptr->count, GetCount(cpptr->MsgNumbers), IO->Now - cpptr->IOStart ); It = GetNewHashPos(POP3FetchUrls, 0); pthread_mutex_lock(&POP3QueueMutex); { if (GetHashPosFromKey(POP3FetchUrls, SKEY(cpptr->Url), It)) DeleteEntryFromHash(POP3FetchUrls, It); } pthread_mutex_unlock(&POP3QueueMutex); DeleteHashPos(&It); return eAbort; }
void cmd_gvdn(char *argbuf) { const ConfType *pCfg; char *confptr; long min = atol(argbuf); const char *Pos = NULL; const char *PPos = NULL; const char *HKey; long HKLen; StrBuf *Line; StrBuf *Config; StrBuf *Cfg; StrBuf *CfgToken; HashList *List; HashPos *It; void *vptr; List = NewHash(1, NULL); Cfg = NewStrBufPlain(config.c_fqdn, -1); Put(List, SKEY(Cfg), Cfg, HFreeStrBuf); Cfg = NULL; confptr = CtdlGetSysConfig(INTERNETCFG); Config = NewStrBufPlain(confptr, -1); free(confptr); Line = NewStrBufPlain(NULL, StrLength(Config)); CfgToken = NewStrBufPlain(NULL, StrLength(Config)); while (StrBufSipLine(Line, Config, &Pos)) { if (Cfg == NULL) Cfg = NewStrBufPlain(NULL, StrLength(Line)); PPos = NULL; StrBufExtract_NextToken(Cfg, Line, &PPos, '|'); StrBufExtract_NextToken(CfgToken, Line, &PPos, '|'); if (GetHash(CfgNameHash, SKEY(CfgToken), &vptr) && (vptr != NULL)) { pCfg = (ConfType *) vptr; if (pCfg->Type <= min) { Put(List, SKEY(Cfg), Cfg, HFreeStrBuf); Cfg = NULL; } } } cprintf("%d Valid Domains\n", LISTING_FOLLOWS); It = GetNewHashPos(List, 1); while (GetNextHashPos(List, It, &HKLen, &HKey, &vptr)) { cputbuf(vptr); cprintf("\n"); } cprintf("000\n"); DeleteHashPos(&It); DeleteHash(&List); FreeStrBuf(&Cfg); FreeStrBuf(&Line); FreeStrBuf(&CfgToken); FreeStrBuf(&Config); }
/* * Scan a room's netconfig to determine whether it requires POP3 aggregation */ void pop3client_scan_room(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCFG) { const RoomNetCfgLine *pLine; void *vptr; pthread_mutex_lock(&POP3QueueMutex); if (GetHash(POP3QueueRooms, LKEY(qrbuf->QRnumber), &vptr)) { pthread_mutex_unlock(&POP3QueueMutex); EVP3CQ_syslog(LOG_DEBUG, "pop3client: [%ld] %s already in progress.", qrbuf->QRnumber, qrbuf->QRname); return; } pthread_mutex_unlock(&POP3QueueMutex); if (server_shutting_down) return; pLine = OneRNCFG->NetConfigs[pop3client]; while (pLine != NULL) { pop3aggr *cptr; cptr = (pop3aggr *) malloc(sizeof(pop3aggr)); memset(cptr, 0, sizeof(pop3aggr)); ///TODO do we need this? cptr->roomlist_parts=1; cptr->RoomName = NewStrBufPlain(qrbuf->QRname, -1); cptr->pop3user = NewStrBufDup(pLine->Value[1]); cptr->pop3pass = NewStrBufDup(pLine->Value[2]); cptr->Url = NewStrBuf(); cptr->Host = NewStrBufDup(pLine->Value[0]); cptr->keep = atol(ChrPtr(pLine->Value[3])); cptr->interval = atol(ChrPtr(pLine->Value[4])); StrBufAppendBufPlain(cptr->Url, HKEY("pop3://"), 0); StrBufUrlescUPAppend(cptr->Url, cptr->pop3user, NULL); StrBufAppendBufPlain(cptr->Url, HKEY(":"), 0); StrBufUrlescUPAppend(cptr->Url, cptr->pop3pass, NULL); StrBufAppendBufPlain(cptr->Url, HKEY("@"), 0); StrBufAppendBuf(cptr->Url, cptr->Host, 0); StrBufAppendBufPlain(cptr->Url, HKEY("/"), 0); StrBufUrlescAppend(cptr->Url, cptr->RoomName, NULL); ParseURL(&cptr->IO.ConnectMe, cptr->Url, 110); #if 0 /* todo: we need to reunite the url to be shure. */ pthread_mutex_lock(&POP3ueueMutex); GetHash(POP3FetchUrls, SKEY(ptr->Url), &vptr); use_this_cptr = (pop3aggr *)vptr; if (use_this_rncptr != NULL) { /* mustn't attach to an active session */ if (use_this_cptr->RefCount > 0) { DeletePOP3Cfg(cptr); /// Count->count--; } else { long *QRnumber; StrBufAppendBufPlain( use_this_cptr->rooms, qrbuf->QRname, -1, 0); if (use_this_cptr->roomlist_parts == 1) { use_this_cptr->OtherQRnumbers = NewHash(1, lFlathash); } QRnumber = (long*)malloc(sizeof(long)); *QRnumber = qrbuf->QRnumber; Put(use_this_cptr->OtherQRnumbers, LKEY(qrbuf->QRnumber), QRnumber, NULL); use_this_cptr->roomlist_parts++; } pthread_mutex_unlock(&POP3QueueMutex); continue; } pthread_mutex_unlock(&RSSQueueMutex); #endif cptr->n = Pop3ClientID++; pthread_mutex_lock(&POP3QueueMutex); Put(POP3FetchUrls, SKEY(cptr->Url), cptr, DeletePOP3Aggregator); pthread_mutex_unlock(&POP3QueueMutex); pLine = pLine->next; } }
/* * Load BBS config file. */ void load_config(void) { FILE *fpConfig; char *word = '\0'; bool fMatch= FALSE; log_string("Load_config: Loading config file"); fclose(fpReserve); if (!(fpConfig = fopen(CONFIG_FILE, "r"))) { bbs_bug("Load_config: Could not open to read %s", CONFIG_FILE); fpReserve = fopen(NULL_FILE, "r"); config.bbs_name = "(Noname)"; config.bbs_email = "userid@host"; config.bbs_host = "localhost"; config.bbs_port = 3000; config.bbs_version = "3.0"; config.bbs_flags = 0; config.bbs_state = "Turkiye"; return; } for (;;) { word = feof(fpConfig) ? "End" : fread_word(fpConfig); fMatch = FALSE; switch (UPPER(word[0])) { case '*': case '#': fread_to_eol(fpConfig); fMatch = TRUE; break; case 'E': SKEY( "Email", config.bbs_email, fget_string(fpConfig)) ; if (!str_cmp(word, "End")) { fclose(fpConfig); fpReserve = fopen(NULL_FILE, "r"); log_string("Load_config: Done"); return; } break; case 'F': KEY( "Flags", config.bbs_flags, fread_flag(fpConfig)) ; break; case 'H': SKEY( "Host", config.bbs_host, fget_string(fpConfig)) ; break; case 'N': SKEY( "Name", config.bbs_name, fget_string(fpConfig)) ; break; case 'P': KEY( "Port", config.bbs_port, fread_number(fpConfig)) ; break; case 'S': SKEY( "State", config.bbs_state, fget_string(fpConfig)) ; break; case 'V': SKEY( "Version", config.bbs_version, fget_string(fpConfig)) ; break; } if (!fMatch) { bbs_bug("Load_config: No match '%s'", word); exit(1); } } return; }
/* * New code for loading classes from file. */ bool fread_class( char *filename ) { FILE *fp; static CLASS_TYPE class_zero; CLASS_TYPE *cclass; const char *word; char buf [ MAX_STRING_LENGTH ]; bool fMatch; int stat; int level; int i; sprintf( buf, "%s%s", CLASS_DIR, filename ); if ( !( fp = fopen( buf, "r" ) ) ) { perror( buf ); return FALSE; } strcpy( strArea, filename ); fpArea = fp; cclass = (CLASS_TYPE *) alloc_mem ( sizeof( CLASS_TYPE ) ); *cclass = class_zero; cclass->skill_level = (int *) alloc_mem( sizeof( int ) * MAX_SKILL ); cclass->skill_adept = (int *) alloc_mem( sizeof( int ) * MAX_SKILL ); cclass->skill_rating = (int *) alloc_mem( sizeof( int ) * MAX_SKILL ); /* Initialize MAX_SPELL marker so noone can use it. */ cclass->skill_level[MAX_SPELL] = MAX_LEVEL+1; for ( i = 0; i < MAX_SKILL; i++ ) { cclass->skill_level[i] = L_APP; cclass->skill_adept[i] = 0; } for ( i = 0; i <= MAX_LEVEL; i++ ) { cclass->title[i][0] = str_dup( "" ); cclass->title[i][1] = str_dup( "" ); } for ( i = 0; i < MAX_POSE; i++ ) { cclass->pose[i][0] = str_dup( "" ); cclass->pose[i][1] = str_dup( "" ); } for ( ; ; ) { GET_TOKEN( fp, word, "End" ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "AtrPrm", cclass->attr_prime, fread_number( fp, &stat ) ); break; case 'C': break; case 'E': if ( !str_cmp( word, "End" ) ) { fclose( fp ); if ( !class_first ) class_first = cclass; if ( class_last ) class_last->next = cclass; class_last = cclass; fpArea = NULL; return TRUE; } break; case 'G': KEY( "Guild", cclass->guild, fread_number( fp, &stat ) ); break; case 'H': KEY( "Hpmin", cclass->hp_min, fread_number( fp, &stat ) ); KEY( "Hpmax", cclass->hp_max, fread_number( fp, &stat ) ); break; case 'M': KEY( "Mana", cclass->fMana, fread_number( fp, &stat ) ); break; case 'N': SKEY( "Nm", cclass->name ); break; case 'P': if ( !str_cmp( word, "Pose" ) ) { level = fread_number( fp, &stat ); i = fread_number( fp, &stat ); if ( level < MAX_POSE ) { free_string( cclass->pose[level][i] ); cclass->pose[level][i] = fread_string( fp, &stat ); } else bugf( "Fread_class: invalid pose." ); fMatch = TRUE; } break; case 'S': KEY( "SkllAdpt", cclass->max_adept, fread_number( fp, &stat ) ); if ( !str_cmp( word, "Skll" ) ) { int sn; int value1; int value2; int value3; value1 = fread_number( fp, &stat ); value2 = fread_number( fp, &stat ); value3 = fread_number( fp, &stat ); word = fread_word( fp, &stat ); sn = skill_lookup( word ); if ( sn == -1 ) { bugf( "Fread_class: unknown skill: %s.", word ); } else { cclass->skill_level [sn] = value1; cclass->skill_rating[sn] = value2; cclass->skill_adept [sn] = value3; } fMatch = TRUE; } break; case 'T': KEY( "Thac0", cclass->thac0_00, fread_number( fp, &stat ) ); KEY( "Thac47", cclass->thac0_47, fread_number( fp, &stat ) ); if ( !str_cmp( word, "Ttle" ) ) { i = fread_number( fp, &stat ); if ( i <= MAX_LEVEL ) { free_string( cclass->title[i][0] ); free_string( cclass->title[i][1] ); cclass->title[i][0] = fread_string( fp, &stat ); cclass->title[i][1] = fread_string( fp, &stat ); } else bugf( "Fread_class: too many titles." ); fMatch = TRUE; } break; case 'W': SKEY( "WhoNm", cclass->who_name ); KEY( "Wpn", cclass->weapon, fread_number( fp, &stat ) ); break; } if ( !fMatch ) { bugf( "load_class_file: no match: %s", word ); } } return FALSE; }
/* * New code for loading clans from file. */ bool fread_clan( CLAN_DATA *clan, FILE *fp ) { const char *word; bool fMatch; int stat; for ( ; ; ) { GET_TOKEN( fp, word, "End" ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': SKEY( "Chieftain", clan->chieftain ); if ( !str_cmp( word, "Class" ) ) { clan->cclass = class_lookup( temp_fread_string( fp, &stat ) ); fMatch = TRUE; break; } KEY( "ClanHeros", clan->clanheros, fread_number( fp, &stat ) ); KEY( "ClanType", clan->clan_type, fread_number( fp, &stat ) ); KEY( "ClanObjOne", clan->clanobj1, fread_number( fp, &stat ) ); KEY( "ClanObjTwo", clan->clanobj2, fread_number( fp, &stat ) ); KEY( "ClanObjThree", clan->clanobj3, fread_number( fp, &stat ) ); break; case 'D': SKEY( "Desc", clan->description ); KEY( "Donation", clan->donation, fread_number( fp, &stat ) ); break; case 'E': if ( !str_cmp( word, "End" ) ) return TRUE; break; case 'I': KEY( "IllegalPK", clan->illegal_pk, fread_number( fp, &stat ) ); break; case 'M': KEY( "Members", clan->members, fread_number( fp, &stat ) ); KEY( "MKills", clan->mkills, fread_number( fp, &stat ) ); KEY( "MDeaths", clan->mdeaths, fread_number( fp, &stat ) ); SKEY( "Motto", clan->motto ); break; case 'N': SKEY( "Name", clan->name ); break; case 'O': SKEY( "Overlord", clan->overlord ); break; case 'P': KEY( "PKills", clan->pkills, fread_number( fp, &stat ) ); KEY( "PDeaths", clan->pdeaths, fread_number( fp, &stat ) ); break; case 'R': KEY( "Recall", clan->recall, fread_number( fp, &stat ) ); break; case 'S': KEY( "Score", clan->score, fread_number( fp, &stat ) ); KEY( "Subchiefs", clan->subchiefs, fread_number( fp, &stat ) ); break; case 'W': SKEY( "WhoName", clan->who_name ); break; } if ( !fMatch ) { bugf( "Load_clan_file: no match: %s", word ); } } return FALSE; }
void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { StrBuf *Recipient; StrBuf *RemoteRoom; const char *Pos = NULL; struct CtdlMessage *msg = NULL; struct CitContext *CCC = CC; struct ser_ret sermsg; char buf[SIZ]; char filename[PATH_MAX]; FILE *fp; StrBuf *Buf = NULL; int i; int bang = 0; int send = 1; if (sc->Users[ignet_push_share] == NULL) return; /* * Process IGnet push shares */ msg = CM_Duplicate(omsg); /* Prepend our node name to the Path field whenever * sending a message to another IGnet node */ Netmap_AddMe(msg, HKEY("username")); /* * Determine if this message is set to be deleted * after sending out on the network */ if (!CM_IsEmpty(msg, eSpecialField)) { if (!strcasecmp(msg->cm_fields[eSpecialField], "CANCEL")) { *delete_after_send = 1; } } /* Now send it to every node */ Recipient = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share])); RemoteRoom = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share])); while ((Pos != StrBufNOTNULL) && StrBufExtract_NextToken(Recipient, sc->Users[ignet_push_share], &Pos, ',')) { StrBufExtract_NextToken(RemoteRoom, sc->Users[ignet_push_share], &Pos, ','); send = 1; NewStrBufDupAppendFlush(&Buf, Recipient, NULL, 1); /* Check for valid node name */ if (CtdlIsValidNode(NULL, NULL, Buf, sc->working_ignetcfg, sc->the_netmap) != 0) { QN_syslog(LOG_ERR, "Invalid node <%s>\n", ChrPtr(Recipient)); send = 0; } /* Check for split horizon */ QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields[eMessagePath]); bang = num_tokens(msg->cm_fields[eMessagePath], '!'); if (bang > 1) { for (i=0; i<(bang-1); ++i) { extract_token(buf, msg->cm_fields[eMessagePath], i, '!', sizeof buf); QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", buf, ChrPtr(Recipient)) ; if (!strcasecmp(buf, ChrPtr(Recipient))) { send = 0; break; } } QN_syslog(LOG_INFO, " %sSending to %s\n", (send)?"":"Not ", ChrPtr(Recipient)); } /* Send the message */ if (send == 1) { /* * Force the message to appear in the correct * room on the far end by setting the C field * correctly */ if (StrLength(RemoteRoom) > 0) { CM_SetField(msg, eRemoteRoom, SKEY(RemoteRoom)); } else { CM_SetField(msg, eRemoteRoom, CCC->room.QRname, strlen(CCC->room.QRname)); } /* serialize it for transmission */ CtdlSerializeMessage(&sermsg, msg); if (sermsg.len > 0) { /* write it to a spool file */ snprintf(filename, sizeof(filename), "%s/%s@%lx%x", ctdl_netout_dir, ChrPtr(Recipient), time(NULL), rand() ); QN_syslog(LOG_DEBUG, "Appending to %s\n", filename); fp = fopen(filename, "ab"); if (fp != NULL) { fwrite(sermsg.ser, sermsg.len, 1, fp); fclose(fp); } else { QN_syslog(LOG_ERR, "%s: %s\n", filename, strerror(errno)); } /* free the serialized version */ free(sermsg.ser); } } } FreeStrBuf(&Buf); FreeStrBuf(&Recipient); FreeStrBuf(&RemoteRoom); CM_Free(msg); }
int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf) { const char *Args; void *vLine, *vHandler; const char *Pos = NULL; Hdr->HR.ReqLine = Line; /* The requesttype... GET, POST... */ StrBufExtract_token(Buf, Hdr->HR.ReqLine, 0, ' '); if (GetHash(HttpReqTypes, SKEY(Buf), &vLine) && (vLine != NULL)) { Hdr->HR.eReqType = *(long*)vLine; } else { Hdr->HR.eReqType = eGET; return 1; } StrBufCutLeft(Hdr->HR.ReqLine, StrLength(Buf) + 1); /* the HTTP Version... */ StrBufExtract_token(Buf, Hdr->HR.ReqLine, 1, ' '); StrBufCutRight(Hdr->HR.ReqLine, StrLength(Buf) + 1); if (StrLength(Buf) == 0) { Hdr->HR.eReqType = eGET; return 1; } StrBufAppendBuf(Hdr->this_page, Hdr->HR.ReqLine, 0); /* chop Filename / query arguments */ Args = strchr(ChrPtr(Hdr->HR.ReqLine), '?'); if (Args == NULL) /* whe're not that picky about params... TODO: this will spoil '&' in filenames.*/ Args = strchr(ChrPtr(Hdr->HR.ReqLine), '&'); if (Args != NULL) { Args ++; /* skip the ? */ StrBufPlain(Hdr->PlainArgs, Args, StrLength(Hdr->HR.ReqLine) - (Args - ChrPtr(Hdr->HR.ReqLine))); StrBufCutAt(Hdr->HR.ReqLine, 0, Args - 1); } /* don't parse them yet, maybe we don't even care... */ /* now lookup what we are going to do with this... */ /* skip first slash */ StrBufExtract_NextToken(Buf, Hdr->HR.ReqLine, &Pos, '/'); do { StrBufExtract_NextToken(Buf, Hdr->HR.ReqLine, &Pos, '/'); GetHash(HandlerHash, SKEY(Buf), &vHandler), Hdr->HR.Handler = (WebcitHandler*) vHandler; if (Hdr->HR.Handler == NULL) break; /* * If the request is prefixed by "/webcit" then chop that off. This * allows a front end web server to forward all /webcit requests to us * while still using the same web server port for other things. */ if ((Hdr->HR.Handler->Flags & URLNAMESPACE) != 0) continue; break; } while (1); /* remove the handlername from the URL */ if ((Pos != NULL) && (Pos != StrBufNOTNULL)){ StrBufCutLeft(Hdr->HR.ReqLine, Pos - ChrPtr(Hdr->HR.ReqLine)); } if (Hdr->HR.Handler != NULL) { if ((Hdr->HR.Handler->Flags & BOGUS) != 0) { return 1; } Hdr->HR.DontNeedAuth = ( ((Hdr->HR.Handler->Flags & ISSTATIC) != 0) || ((Hdr->HR.Handler->Flags & ANONYMOUS) != 0) ); } else { /* If this is a "flat" request for the root, display the configured landing page. */ int return_value; StrBuf *NewLine = NewStrBuf(); Hdr->HR.DontNeedAuth = 1; StrBufAppendPrintf(NewLine, "GET /landing?go=%s?failvisibly=1 HTTP/1.0", ChrPtr(Buf)); if (verbose) syslog(LOG_DEBUG, "Replacing with: %s", ChrPtr(NewLine)); return_value = ReadHttpSubject(Hdr, NewLine, Buf); FreeStrBuf(&NewLine); return return_value; } return 0; }
void network_process_digest(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { struct CtdlMessage *msg = NULL; if (sc->Users[digestrecp] == NULL) return; /* If there are digest recipients, we have to build a digest */ if (sc->digestfp == NULL) { sc->digestfp = create_digest_file(&sc->room, 1); if (sc->digestfp == NULL) return; sc->haveDigest = ftell(sc->digestfp) > 0; if (!sc->haveDigest) { fprintf(sc->digestfp, "Content-type: text/plain\n\n"); } sc->haveDigest = 1; } msg = CM_Duplicate(omsg); if (msg != NULL) { sc->haveDigest = 1; fprintf(sc->digestfp, " -----------------------------------" "------------------------------------" "-------\n"); fprintf(sc->digestfp, "From: "); if (!CM_IsEmpty(msg, eAuthor)) { fprintf(sc->digestfp, "%s ", msg->cm_fields[eAuthor]); } if (!CM_IsEmpty(msg, erFc822Addr)) { fprintf(sc->digestfp, "<%s> ", msg->cm_fields[erFc822Addr]); } else if (!CM_IsEmpty(msg, eNodeName)) { fprintf(sc->digestfp, "@%s ", msg->cm_fields[eNodeName]); } fprintf(sc->digestfp, "\n"); if (!CM_IsEmpty(msg, eMsgSubject)) { fprintf(sc->digestfp, "Subject: %s\n", msg->cm_fields[eMsgSubject]); } CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); safestrncpy(CC->preferred_formats, "text/plain", sizeof CC->preferred_formats); CtdlOutputPreLoadedMsg(msg, MT_CITADEL, HEADERS_NONE, 0, 0, 0); StrBufTrim(CC->redirect_buffer); fwrite(HKEY("\n"), 1, sc->digestfp); fwrite(SKEY(CC->redirect_buffer), 1, sc->digestfp); fwrite(HKEY("\n"), 1, sc->digestfp); FreeStrBuf(&CC->redirect_buffer); sc->num_msgs_spooled += 1; CM_Free(msg); } }
/* * Read in the request */ int ReadHTTPRequest (ParsedHttpHdrs *Hdr) { const char *pch, *pchs, *pche; OneHttpHeader *pHdr; StrBuf *Line, *LastLine, *HeaderName; int nLine = 0; void *vF; int isbogus = 0; HeaderName = NewStrBuf(); LastLine = NULL; do { nLine ++; Line = NewStrBufPlain(NULL, SIZ / 4); if (ClientGetLine(Hdr, Line) < 0) return 1; if (StrLength(Line) == 0) { FreeStrBuf(&Line); continue; } if (nLine == 1) { Hdr->HTTPHeaders = NewHash(1, NULL); pHdr = (OneHttpHeader*) malloc(sizeof(OneHttpHeader)); memset(pHdr, 0, sizeof(OneHttpHeader)); pHdr->Val = Line; Put(Hdr->HTTPHeaders, HKEY("GET /"), pHdr, DestroyHttpHeaderHandler); if (verbose || strstr(ChrPtr(Line), "sslg") == NULL) syslog(LOG_DEBUG, "%s", ChrPtr(Line)); isbogus = ReadHttpSubject(Hdr, Line, HeaderName); if (isbogus) break; continue; } /* Do we need to Unfold? */ if ((LastLine != NULL) && (isspace(*ChrPtr(Line)))) { pch = pchs = ChrPtr(Line); pche = pchs + StrLength(Line); while (isspace(*pch) && (pch < pche)) pch ++; StrBufCutLeft(Line, pch - pchs); StrBufAppendBuf(LastLine, Line, 0); FreeStrBuf(&Line); continue; } StrBufSanitizeAscii(Line, (char)0xa7); StrBufExtract_token(HeaderName, Line, 0, ':'); pchs = ChrPtr(Line); pche = pchs + StrLength(Line); pch = pchs + StrLength(HeaderName) + 1; pche = pchs + StrLength(Line); while ((pch < pche) && isspace(*pch)) pch ++; StrBufCutLeft(Line, pch - pchs); StrBufUpCase(HeaderName); pHdr = (OneHttpHeader*) malloc(sizeof(OneHttpHeader)); memset(pHdr, 0, sizeof(OneHttpHeader)); pHdr->Val = Line; if (GetHash(HttpHeaderHandler, SKEY(HeaderName), &vF) && (vF != NULL)) { OneHttpHeader *FHdr = (OneHttpHeader*) vF; pHdr->H = FHdr->H; pHdr->HaveEvaluator = 1; } Put(Hdr->HTTPHeaders, SKEY(HeaderName), pHdr, DestroyHttpHeaderHandler); LastLine = Line; } while (Line != NULL); FreeStrBuf(&HeaderName); return isbogus; }
/* * Implements the GETACL command. */ void imap_getacl(int num_parms, ConstStr *Params) { char roomname[ROOMNAMELEN]; char savedroom[ROOMNAMELEN]; int msgs, new; int ret; struct ctdluser temp; struct cdbdata *cdbus; int ra; StrBuf *rights; if (num_parms != 3) { IReply("BAD usage error"); return; } /* * Search for the specified room or folder */ ret = imap_grabroom(roomname, Params[2].Key, 1); if (ret != 0) { IReply("NO Invalid mailbox name or access denied"); return; } /* * CtdlUserGoto() formally takes us to the desired room. (If another * folder is selected, save its name so we can return there!!!!!) */ if (IMAP->selected) { strcpy(savedroom, CC->room.QRname); } CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL); IAPuts("* ACL "); IPutCParamStr(2); /* * Traverse the userlist */ rights = NewStrBuf(); cdb_rewind(CDB_USERS); while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) { memset(&temp, 0, sizeof temp); memcpy(&temp, cdbus->ptr, sizeof temp); cdb_free(cdbus); CtdlRoomAccess(&CC->room, &temp, &ra, NULL); if (!IsEmptyStr(temp.fullname)) { imap_acl_flags(rights, ra); if (StrLength(rights) > 0) { IAPuts(" "); IPutStr(temp.fullname, strlen(temp.fullname)); IAPuts(" "); iaputs(SKEY( rights)); } } } FreeStrBuf(&rights); IAPuts("\r\n"); /* * If another folder is selected, go back to that room so we can resume * our happy day without violent explosions. */ if (IMAP->selected) { CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL); }
void fread_social( FILE *fp ) { const char *word; SOC_INDEX_DATA *social; bool fMatch; int stat; social = new_social( ); for ( ; ; ) { GET_TOKEN( fp, word, "End" ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': SKEY( "CharNoArg", social->char_no_arg ); SKEY( "CharFound", social->char_found ); SKEY( "CharAuto", social->char_auto ); break; case 'E': if ( !str_cmp( word, "End" ) ) { if ( !social->name ) { bugf( "Fread_social: Name not found" ); free_social( social ); return; } if ( !social->char_no_arg ) { bugf( "Fread_social: CharNoArg not found" ); free_social( social ); return; } add_social( social ); return; } break; case 'N': SKEY( "Name", social->name ); break; case 'O': SKEY( "OthersNoArg", social->others_no_arg ); SKEY( "OthersFound", social->others_found ); SKEY( "OthersAuto", social->others_auto ); break; case 'V': SKEY( "VictFound", social->vict_found ); break; } if ( !fMatch ) { bugf( "Fread_social: no match: %s. Skipping to next line.", word ); fread_to_eol( fp ); } } return; }
// // Implements the ARTICLE, HEAD, BODY, and STAT commands. // (These commands all accept the same parameters; they differ only in how they output the retrieved message.) // void nntp_article(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; citnntp *nntpstate = (citnntp *) CC->session_specific_data; char which_command[16]; int acmd = 0; char requested_article[256]; long requested_msgnum = 0; char *lb, *rb = NULL; int must_change_currently_selected_article = 0; // We're going to store one of these values in the variable 'acmd' so that // we can quickly check later which version of the output we want. enum { ARTICLE, HEAD, BODY, STAT }; extract_token(which_command, cmd, 0, ' ', sizeof which_command); if (!strcasecmp(which_command, "article")) { acmd = ARTICLE; } else if (!strcasecmp(which_command, "head")) { acmd = HEAD; } else if (!strcasecmp(which_command, "body")) { acmd = BODY; } else if (!strcasecmp(which_command, "stat")) { acmd = STAT; } else { cprintf("500 I'm afraid I can't do that.\r\n"); return; } // Which NNTP command was issued, determines whether we will fetch headers, body, or both. int headers_only = HEADERS_ALL; if (acmd == HEAD) headers_only = HEADERS_FAST; else if (acmd == BODY) headers_only = HEADERS_NONE; else if (acmd == STAT) headers_only = HEADERS_FAST; // now figure out what the client is asking for. extract_token(requested_article, cmd, 1, ' ', sizeof requested_article); lb = strchr(requested_article, '<'); rb = strchr(requested_article, '>'); requested_msgnum = atol(requested_article); // If no article number or message-id is specified, the client wants the "currently selected article" if (IsEmptyStr(requested_article)) { if (nntpstate->current_article_number < 1) { cprintf("420 No current article selected\r\n"); return; } requested_msgnum = nntpstate->current_article_number; must_change_currently_selected_article = 1; // got it -- now fall through and keep going } // If the requested article is numeric, it maps directly to a message number. Good. else if (requested_msgnum > 0) { must_change_currently_selected_article = 1; // good -- fall through and keep going } // If the requested article has angle brackets, the client wants a specific message-id. // We don't know how to do that yet. else if ( (lb != NULL) && (rb != NULL) && (lb < rb) ) { must_change_currently_selected_article = 0; cprintf("500 I don't know how to fetch by message-id yet.\r\n"); // FIXME return; } // Anything else is noncompliant gobbledygook and should die in a car fire. else { must_change_currently_selected_article = 0; cprintf("500 syntax error\r\n"); return; } // At this point we know the message number of the "article" being requested. // We have an awesome API call that does all the heavy lifting for us. char *fetched_message_id = NULL; CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); int fetch = CtdlOutputMsg(requested_msgnum, MT_RFC822, // output in RFC822 format ... sort of headers_only, // headers, body, or both? 0, // don't do Citadel protocol responses 1, // CRLF newlines NULL, // teh whole thing, not just a section 0, // no flags yet ... maybe new ones for Path: etc ? NULL, NULL, &fetched_message_id // extract the message ID from the message as we go... ); StrBuf *msgtext = CC->redirect_buffer; CC->redirect_buffer = NULL; if (fetch != om_ok) { cprintf("423 no article with that number\r\n"); FreeStrBuf(&msgtext); return; } // RFC3977 6.2.1.2 specifes conditions under which the "currently selected article" // MUST or MUST NOT be set to the message we just referenced. if (must_change_currently_selected_article) { nntpstate->current_article_number = requested_msgnum; } // Now give the client what it asked for. if (acmd == ARTICLE) { cprintf("220 %ld <%s>\r\n", requested_msgnum, fetched_message_id); } if (acmd == HEAD) { cprintf("221 %ld <%s>\r\n", requested_msgnum, fetched_message_id); } if (acmd == BODY) { cprintf("222 %ld <%s>\r\n", requested_msgnum, fetched_message_id); } if (acmd == STAT) { cprintf("223 %ld <%s>\r\n", requested_msgnum, fetched_message_id); FreeStrBuf(&msgtext); return; } client_write(SKEY(msgtext)); cprintf(".\r\n"); // this protocol uses a dot terminator FreeStrBuf(&msgtext); if (fetched_message_id) free(fetched_message_id); }