static WJElement _WJECopy(_WJElement *parent, WJElement original, WJECopyCB copycb, void *data, const char *file, const int line) { _WJElement *l = NULL; _WJElement *o; WJElement c; char *tmp; if (!(o = (_WJElement *) original)) { return(NULL); } if (copycb && !copycb((WJElement) parent, (WJElement) original, data, file, line)) { /* The consumer has rejected this item */ return(NULL); } if ((l = _WJENew(parent, original->name, original->name ? strlen(original->name) : 0, file, line))) { switch ((l->pub.type = original->type)) { default: case WJR_TYPE_UNKNOWN: case WJR_TYPE_NULL: break; case WJR_TYPE_OBJECT: case WJR_TYPE_ARRAY: for (c = original->child; c; c = c->next) { _WJECopy(l, c, copycb, data, file, line); } break; case WJR_TYPE_STRING: if ((tmp = WJEString(original, NULL, WJE_GET, ""))) { l->value.string = MemStrdup(tmp); l->pub.length = original->length; } else { l->value.string = MemStrdup(""); l->pub.length = 0; } break; case WJR_TYPE_NUMBER: l->value.number.negative = o->value.number.negative; l->value.number.i = o->value.number.i; l->value.number.d = o->value.number.d; l->value.number.hasDecimalPoint = o->value.number.hasDecimalPoint; break; case WJR_TYPE_TRUE: case WJR_TYPE_BOOL: case WJR_TYPE_FALSE: l->value.boolean = WJEBool(original, NULL, WJE_GET, FALSE); break; } } return((WJElement) l); }
/** * Open the Store database for this user. Updates the storedb handle of * the StoreClient to contain an SQLite handle to the Store. * \param client storeclient we're working for * \param user name of the store (usually, the username) * \return 0 on success, error codes otherwise */ int StoreDBOpen(StoreClient *client, const char *user) { char path[XPL_MAX_PATH +1]; DBPoolEntry *entry = NULL; // try to find the handle in the pool - first, lock the pool XplMutexLock(StoreAgent.dbpool.lock); { // find the entry entry = (DBPoolEntry *) BongoHashtableGet(StoreAgent.dbpool.entries, user); if (entry == NULL) { // no such entry, need to create one - we // do it here while locked entry = MemNew0(DBPoolEntry, 1); entry->user = MemStrdup(user); entry->clients = 0; if (BongoHashtablePutNoReplace(StoreAgent.dbpool.entries, MemStrdup(user), (void *)entry)) { // couldn't insert the new entry for whatever reason :( DBPoolEntryDelete(entry); goto db_fail; } // this bit is slow, but I can't think how we could // do this outside the dbpool.lock without being racy :( snprintf(path, XPL_MAX_PATH, "%s/%s/store.db", StoreAgent.store.rootDir, user); entry->handle = MsgSQLOpen(path, &client->memstack, 3000); if (entry->handle == NULL) { BongoHashtableRemove(StoreAgent.dbpool.entries, (void *)user); DBPoolEntryDelete(entry); goto db_fail; } } entry->clients++; } // unlock the pool on success XplMutexUnlock(StoreAgent.dbpool.lock); client->storedb = entry->handle; return 0; db_fail: // unlock the pool on failure XplMutexUnlock(StoreAgent.dbpool.lock); return -1; }
static void ReadEnvelope(ItipAgentClient *client, char *envelope, BongoSList **usersOut) { char *ptr; char *delim; char *user; *usersOut = NULL; ptr = envelope; /* Queue-agent specific code. This code just prints out the envelope */ while (*ptr) { switch(*ptr++) { case QUEUE_RECIP_LOCAL : case QUEUE_RECIP_MBOX_LOCAL : delim = strchr(ptr, ' '); if (delim) { user = MemStrndup(ptr, delim - ptr); } else { user = MemStrdup(ptr); } *usersOut = BongoSListPrepend(*usersOut, user); } BONGO_ENVELOPE_NEXT(ptr); } }
EXPORT XplBool WJERename(WJElement document, const char *name) { _WJElement *current = (_WJElement *) document; WJElement e; if (!document) { return(FALSE); } /* Look for any siblings with that name, and fail if found */ if (name && document->parent) { for (e = document->parent->child; e; e = e->next) { if (e != document && !stricmp(e->name, name)) { return(FALSE); } } } /* Free the previous name if needed */ if (document->name && current->_name != document->name) { MemRelease(&document->name); } /* Set the new name */ if (name) { if (!(document->name = MemStrdup(name))) { return(FALSE); } } else { document->name = NULL; } return(TRUE); }
static char * DisplaySubject(const char *subject) { char *newSubject; const char *ptr; char *ptr2; int length; BOOL done; newSubject = MemStrdup(subject); length = strlen(newSubject); ptr = subject; do { done = TRUE; if ((*ptr == '[') && (newSubject[length - 1] == ']')) { /* Remove enclosing brackets */ newSubject[--length] = '\0'; ptr++; done = FALSE; } else if (*ptr == '[') { /* Remove bracketed prefixes (like mailing list names) */ int depth = 0; do { if (*ptr == '[') { depth++; } else if (*ptr == ']') { depth--; } ptr++; } while (*ptr && (depth > 0)); done = FALSE; } else if (isspace(*ptr)) { ptr++; done = FALSE; } else { unsigned int i; for (i = 0; i < (sizeof(stripPrefixes) / sizeof(char *)); i++) { char *prefix = stripPrefixes[i]; int length = strlen(prefix); if (!XplStrNCaseCmp(ptr, prefix, length)) { ptr += strlen(prefix); done = FALSE; } } } } while (!done && *ptr != '\0'); memmove(newSubject, ptr, strlen(ptr) + 1); for (ptr2 = newSubject; *ptr2 != '\0'; ptr2++) { if (*ptr2 == '\t') { *ptr2 = ' '; } } return newSubject; }
static void ImportFile(const char *filename, char *destdir, FILE *tznames) { BongoCalObject *cal; BongoJsonObject *obj = NULL; BongoHashtable *tzs = NULL; BongoHashtableIter iter; obj = ConvertFile(filename); if (!obj) { return; } cal = BongoCalObjectNew(obj); if (!cal) { return; } tzs = BongoCalObjectGetTimezones(cal); if (!tzs) { fprintf(stderr, "Couldn't get timezones from ical file %s\n", filename); return; } for (BongoHashtableIterFirst(tzs, &iter); iter.key != NULL; BongoHashtableIterNext(tzs, &iter)) { const char *tzid = iter.key; char path[PATH_MAX]; FILE *f; char *tz; char *name; char *p; snprintf(path, PATH_MAX, "%s/%s", destdir, GetFilename(tzid)); f = fopen(path, "w"); fprintf(f, "{ \"version\": { \"value\": \"2.0\" }, \"components\":["); tz = BongoJsonObjectToString(((BongoCalTimezone*)iter.value)->json); fwrite(tz, 1, strlen(tz), f); fprintf(f, "] }"); name = MemStrdup(strrchr(tzid, '/') + 1); for (p = name; *p != '\0'; p++) { if (*p == '_') { *p = ' '; } } fprintf(tznames, "%s|%s\n", name, tzid); fclose(f); } }
int main(int argc, char **argv) { int r = 0; WJElement doc = NULL; WJReader reader; int i, a, line; char *j, *x; MemoryManagerOpen("wjeunit"); /* Begin tests */ for (a = 1; a < argc; a++) { for (i = 0; tests[i].name && tests[i].cb; i++) { if (!stricmp(argv[a], tests[i].name)) { break; } } if (!tests[i].cb) { fprintf(stderr, "Ignoring unknown test \"%s\"\n", argv[a]); } else { /* Reopen the JSON for each test in case a test modified it */ if ((j = MemStrdup(json))) { /* Correct the quotes */ for (x = j; *x; x++) { if (*x == '\'') *x = '"'; } // printf("JSON:\n%s\n", j); if ((reader = WJROpenMemDocument(j, NULL, 0))) { doc = WJEOpenDocument(reader, NULL, NULL, NULL); WJRCloseDocument(reader); } MemRelease(&j); } if (!doc) { fprintf(stderr, "error: Could not parse JSON document\n"); MemoryManagerClose("wjeunit"); return(1); } if ((line = tests[i].cb(doc))) { fprintf(stderr, "error: %s:%d: Failed test \"%s\"\n", __FILE__, line, tests[i].name); r = 1; } WJECloseDocument(doc); } } /* All done */ MemoryManagerClose("wjeunit"); return(r); }
static char * NormalizeSubject(const char *subject) { char *ret; char *p; ret = MemStrdup(subject); for (p = ret; *p != '\0'; p++) { if (isspace(*p)) { char *p1; for (p1 = p; *p1 != '\0'; p1++) { *p1 = *(p1 + 1); } } } return ret; }
/** * Start a new Query parser. * \param state New parser state - this gets initialised for future use * \param query String containing the query to parse * \param max_expr Maximum expression parts we will allow * \return 0 if successfully allocated, error codes otherwise */ int QueryParserStart(struct parser_state *state, const char *query, int max_expr) { //size_t q_size; state->entries = max_expr; //q_size = sizeof(struct expression) * (max_expr + 1); state->start = MemNew0(struct expression, max_expr); if (state->start == NULL) return -1; state->last = state->start; state->query = MemStrdup(query); if (state->query == NULL) { MemFree(state->start); return -2; } state->query_ptr = state->query; return 0; }
BongoThreadPool * BongoThreadPoolNew(const char *name, int stackSize, int minimum, int maximum, int minSleep) { BongoThreadPool *pool; /* FIXME: do we want a private mempool for work items? */ pool = MemMalloc(sizeof(BongoThreadPool)); memset(pool, 0, sizeof(BongoThreadPool)); XplMutexInit(pool->lock); XplOpenLocalSemaphore(pool->todo, 0); pool->minimum = minimum; pool->maximum = maximum; pool->minSleep = minSleep; pool->name = MemStrdup(name); pool->stackSize = stackSize; return pool; }
static BOOL ReadConfiguration(void) { unsigned int i; if (! ReadBongoConfiguration(GlobalConfig, "global")) { return FALSE; } if (! ReadBongoConfiguration(AVirusConfigSchema, "antivirus")) { return FALSE; } for (i=0; i < AVirus.clamd.hostlist->len; i++) { char *hostitem = g_array_index(AVirus.clamd.hostlist, char*, i); char *lHost = MemStrdup(hostitem); char *host; int port=AVIRUS_DEFAULT_PORT, weight=AVIRUS_DEFAULT_WEIGHT; ParseHost(lHost, &host, &port, &weight); ConnAddressPoolAddHost(&AVirus.clamd.hosts, host, port, weight); MemFree(lHost); } return TRUE; }
int main(int argc, char **argv) { FILE *in = NULL; WJElement doc = NULL; WJElement current = NULL; int r = 0; WJReader reader; char *cmd; char line[1024]; /* Print pretty documents by default */ wje.pretty = TRUE; /* Print base 10 by default */ wje.base = 10; if (argc > 2) { /* Umm, we only allow one argument... a filename */ usage(argv[0]); return(1); } MemoryManagerOpen("wje-cli"); if (argc == 2) { if (!stricmp(argv[1], "--help") || !stricmp(argv[1], "-h")) { usage(argv[0]); MemoryManagerClose("wje-cli"); return(0); } if (!(in = fopen(argv[1], "rb"))) { perror(NULL); MemoryManagerClose("wje-cli"); return(2); } /* A filename was specified on the command line. Does this look like a script, or a JSON document? */ if (fgets(line, sizeof(line), in) && !strncmp(line, "#!", 2) ) { /* This looks like a script, read commands from this file */ ; } else { /* Assume it is a JSON document, rewind back to the start. */ rewind(in); if ((reader = WJROpenFILEDocument(in, NULL, 0))) { doc = WJEOpenDocument(reader, NULL, NULL, NULL); WJRCloseDocument(reader); wje.filename = MemStrdup(argv[1]); } fclose(in); in = NULL; if (!doc) { fprintf(stderr, "Could not parse JSON document: %s\n", argv[1]); MemoryManagerClose("wje-cli"); return(3); } } } if (!in) { /* Read commands from standard in */ in = stdin; } if (!doc) { /* Start with an empty document if one wasn't specified */ doc = WJEObject(NULL, NULL, WJE_SET); } current = doc; for (;;) { /* Read the next command */ if (in == stdin && isatty(fileno(stdin))) { fprintf(stdout, "wje"); if (r) { fprintf(stdout, " (%d)", r); } fprintf(stdout, "> "); fflush(stdout); } if (fgets(line, sizeof(line), in)) { cmd = skipspace(line); } else { cmd = NULL; } if (!cmd || !*cmd) { /* Ignore blank lines */ } else { r = runcmd(&doc, ¤t, cmd); } cmd = NULL; if (feof(in) || wje.exiting) { break; } } if (doc) { WJECloseDocument(doc); doc = NULL; } if (in && in != stdin) { fclose(in); in = NULL; } if (wje.filename) { MemRelease(&wje.filename); } MemoryManagerClose("wje-cli"); return(r); }
/** * Create the SQL query based on the information we've gathered so far and the queries we've parsed. * All queries are of the form: * SELECT <default rows>, <optional props> FROM storeobject, <other needed tables> WHERE <conditions> * ORDER BY <some column> [ASC|DESC] LIMIT <some amount>; * \param builder The builder instance we're using * \param output a char * where we should place the output. Caller frees? (can we do this in Finish?) * \return 0 on success, error codes otherwise. */ int QueryBuilderCreateSQL(QueryBuilder *builder, char **output) { BongoStringBuilder b; unsigned int i; int ccode; if (BongoStringBuilderInit(&b)) { // unable to start... ick return -1; } // basic start for all queries BongoStringBuilderAppend(&b, "SELECT so.guid, so.collection_guid, so.imap_uid, so.filename, so.type, so.flags, so.size, so.time_created, so.time_modified"); // extra columns for additional properties for (i=0; i < builder->properties->len; i++) { StorePropInfo *prop = g_ptr_array_index(builder->properties, i); // only add those columns which we want returned. BongoStringBuilderAppend(&b, ", "); QueryBuilderPropertyToColumn(builder, &b, prop); } BongoStringBuilderAppend(&b, " FROM storeobject so"); // add in the tables that we need if (builder->linkin_conversations) { BongoStringBuilderAppend(&b, " INNER JOIN conversation c ON so.guid=c.guid"); } for (i=0; i < builder->links->len; i++) { ExtraLink *link = g_ptr_array_index(builder->links, i); BongoStringBuilderAppendF(&b, " INNER JOIN links link_%d ON so.guid=link_%d.%s", i, i, link->join_column); } for (i=0; i < builder->properties->len; i++) { StorePropInfo *prop = g_ptr_array_index(builder->properties, i); // only add those columns which we want returned. if ((prop->table_name == NULL) && (prop->column == NULL)) { // FIXME. Both following queries should use bound parameters really. if (prop->type == STORE_PROP_EXTERNAL) { BongoStringBuilderAppendF(&b, " LEFT JOIN properties prop_%d ON so.guid=prop_%d.guid AND prop_%d.name=\"%s\"", i, i, i, prop->name); } else { BongoStringBuilderAppendF(&b, " LEFT JOIN properties prop_%d ON so.guid=prop_%d.guid AND prop_%d.intprop=%d", i, i, i, (int)prop->type); } } } if (builder->int_query || builder->ext_query || (builder->properties->len > 0)) BongoStringBuilderAppend(&b, " WHERE "); // add in any constraints specified on the various columns if (builder->int_query) { if (QueryExpressionToSQL(builder, builder->internal_parser.start, &b)) { ccode = -2; goto abort; } } if (builder->int_query && builder->ext_query) { BongoStringBuilderAppend(&b, " AND "); } if (builder->ext_query) { if (QueryExpressionToSQL(builder, builder->external_parser.start, &b)) { ccode = -3; goto abort; } } // set the order of the query if requested if (builder->order_prop != NULL) { StorePropInfo prop; char *direction = (builder->order_direction == ORDER_ASC)? "ASC" : "DESC"; BongoStringBuilderAppendF(&b, " ORDER BY "); prop.name = (char *)builder->order_prop; StorePropertyFixup(&prop); // FIXME: do we also need the table alias here? BongoStringBuilderAppendF(&b, " %s %s", prop.column, direction); } // set any limit on the results. if (builder->limit_start > 0) { BongoStringBuilderAppendF(&b, " LIMIT %d, %d", builder->limit_start, builder->limit_end); } BongoStringBuilderAppend(&b, ";"); *output = MemStrdup(b.value); BongoStringBuilderDestroy(&b); return 0; abort: BongoStringBuilderDestroy(&b); return ccode; }
BOOL VirusCheck(AVirusClient *client, const char *queueID, BOOL hasFlags, unsigned long msgFlags, unsigned long senderIp, char *senderUserName) { int ccode; long size; BOOL infected = FALSE; Connection *conn; conn = ConnAddressPoolConnect(&(AVirus.clamd.hosts), AVirus.clamd.connectionTimeout); if (conn) { Connection *data; unsigned short port; ConnWrite(conn, "STREAM\r\n", strlen("STREAM\r\n")); ConnFlush(conn); ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE); if (!ccode || strncmp(client->line, "PORT ", strlen("PORT ")) != 0 || (port = atoi(client->line + strlen("PORT "))) == 0) { ConnFree(conn); return -1; } data = ConnAlloc(TRUE); if (!data) { ConnFree(conn); return -1; } memcpy(&data->socketAddress, &conn->socketAddress, sizeof(struct sockaddr_in)); data->socketAddress.sin_port = htons(port); if (ConnConnectEx(data, NULL, 0, NULL, client->conn->trace.destination) < 0) { ConnFree(conn); ConnFree(data); return -1; } size = 0; if (((ccode = NMAPSendCommandF(client->conn, "QRETR %s MESSAGE\r\n", queueID)) != -1) && ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != -1) && ccode == 2023) { char *ptr; ptr = strchr (client->line, ' '); if (ptr) { *ptr = '\0'; } size = atol(client->line); } if (size == 0) { ConnFree(conn); ConnFree(data); return -1; } ccode = ConnReadToConn(client->conn, data, size); ConnFree(data); if ((ccode == -1) || ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != 1000)) { Log(LOG_DEBUG, "result: %d", ccode); ConnFree(conn); return -1; } while ((ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE)) != -1) { char *ptr; ptr = strrchr(client->line, ' '); if (XplStrCaseCmp(ptr + 1, "FOUND") == 0) { *ptr = '\0'; ptr = client->line + strlen("stream: "); #if 0 if(client->foundViruses.used == client->foundViruses.allocated) { client->foundViruses.names = MemRealloc(client->foundViruses.names, sizeof(char*) * (client->foundViruses.allocated + MIME_REALLOC_SIZE)); } client->foundViruses.names[client->foundViruses.used++] = MemStrdup(ptr); XplSafeIncrement(AVirus.stats.viruses); #endif infected = TRUE; } } ConnFree(conn); } return infected; }
/** Callback function. Whenever a new message arrives in the queue that * this agent has registered itself on, NMAP calls back to this function * and provides the agent with the unique hash of the new message. The * connection then remains open, and NMAP goes into slave state while * the agent does all necessary processing. * \param client The connection initiated by the NMAP store. */ static __inline int ProcessConnection(void *clientp, Connection *conn) { AVirusClient *client = clientp; unsigned char *envelopeLine; BOOL hasFlags = FALSE; unsigned long msgFlags = 0; int ccode; unsigned long source = 0; unsigned char *ptr; char *ptr2; char *senderUserName = NULL; BOOL blocked = FALSE; client->conn = conn; ccode = BongoQueueAgentHandshake(client->conn, client->line, client->qID, &client->envelopeLength, &client->messageLength); client->envelope = BongoQueueAgentReadEnvelope(client->conn, client->line, client->envelopeLength, &client->envelopeLines); envelopeLine = client->envelope; while (*envelopeLine) { switch(*envelopeLine) { case QUEUE_FROM: if ((ptr = strchr(envelopeLine, ' '))) { ptr++; if ((ptr2 = strchr(ptr, ' '))) { *ptr2 = '\0'; if (strcmp(ptr, "-") != 0) { senderUserName = MemStrdup(ptr); } *ptr2 = ' '; } } break; case QUEUE_FLAGS: hasFlags = TRUE; msgFlags = atol(envelopeLine+1); break; case QUEUE_ADDRESS: source = atol(envelopeLine+1); break; } BONGO_ENVELOPE_NEXT(envelopeLine); } blocked = VirusCheck(client, client->qID, hasFlags, msgFlags, source, senderUserName); if (blocked == TRUE) { /* we found a virus of some kind. drop the mail */ Log(LOG_DEBUG, "Queue ID %s Infected and blocked", client->qID); ConnWriteF(client->conn, "QDELE %s\r\n", client->qID); ConnFlush(client->conn); /* the rules here are: * 1) notify the sender if they are auth'd * 2) notify postmaster if the flag for such is set */ /* are we auth'd? */ if (senderUserName) { /* create the bounce to the sender */ BounceToSender(client, senderUserName); } if (AVirus.flags & AVIRUS_FLAG_NOTIFY_POSTMASTER) { /* create the bounce to the postmaster */ BounceToPostmaster(client, senderUserName); } } else { Log(LOG_DEBUG, "Queue ID %s clean", client->qID); NMAPSendCommand(client->conn, "QDONE\r\n", 7); ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, FALSE); } if (client->envelope) { MemFree(client->envelope); client->envelope = NULL; } if (senderUserName) { MemFree(senderUserName); } return(0); }