static void imap_handle_continue(ImapSession *session) { if (session->state < CLIENTSTATE_LOGOUT) { if (session->buff && p_string_len(session->buff) > 0) { int e = 0; if ((e = ci_write(session->ci, "%s", (char *)p_string_str(session->buff))) < 0) { int serr = errno; TRACE(TRACE_DEBUG,"ci_write returned error [%s]", strerror(serr)); imap_handle_abort(session); return; } dbmail_imap_session_buff_clear(session); } if (p_string_len(session->ci->write_buffer) > session->ci->write_buffer_offset) ci_write(session->ci, NULL); if (session->command_state == TRUE) imap_session_reset(session); } else { dbmail_imap_session_buff_clear(session); } // handle buffered pending input if (p_string_len(session->ci->read_buffer) > 0) imap_handle_input(session); }
int p_xml_key_append (struct str_xml_key **record, char *key, char *value) { struct str_xml_key *singleton; size_t length; int result = pippolo_true; p_string_trim(key); p_string_trim(value); if ((key) && (value)) { if ((singleton = (struct str_xml_key *) pippolo_malloc(sizeof(str_xml_key)))) { length = p_string_len(value)+1; if ((singleton->value = (char *) pippolo_malloc(length))) { snprintf(singleton->value, length, "%s", value); length = p_string_len(key)+1; if ((singleton->key = (char *) pippolo_malloc(length))) { snprintf(singleton->key, length, "%s", key); singleton->next = *record; *record = singleton; } else pippolo_kill("out of memory, I'm dying bleaaargh"); } else pippolo_kill("out of memory, I'm dying bleaaargh"); } else pippolo_kill("out of memory, I'm dying bleaaargh"); } return result; }
/* * only the main thread may write to the network event * worker threads must use an async queue */ static int64_t imap_session_printf(ImapSession * session, char * message, ...) { va_list ap, cp; uint64_t l; int e = 0; p_string_truncate(session->buff, 0); assert(message); va_start(ap, message); va_copy(cp, ap); p_string_append_vprintf(session->buff, message, cp); va_end(cp); va_end(ap); if ((e = ci_write(session->ci, (char *)p_string_str(session->buff))) < 0) { TRACE(TRACE_DEBUG, "ci_write failed [%d]", e); imap_handle_abort(session); return e; } l = p_string_len(session->buff); p_string_truncate(session->buff, 0); return (int64_t)l; }
void imap_cb_read(void *arg) { ImapSession *session = (ImapSession *) arg; ci_read_cb(session->ci); uint64_t have = p_string_len(session->ci->read_buffer); uint64_t need = session->ci->rbuff_size; int enough = (need>0?(have >= need):(have >= 0)); int state; PLOCK(session->ci->lock); state = session->ci->client_state; PUNLOCK(session->ci->lock); TRACE(TRACE_DEBUG,"state [%d] enough %d: %" PRIu64 "/%" PRIu64 "", state, enough, have, need); if (state & CLIENT_ERR) { imap_session_bailout(session); } else if (state & CLIENT_EOF) { ci_cork(session->ci); if (enough) imap_handle_input(session); else imap_session_bailout(session); } else if (have > 0) imap_handle_input(session); }
size_t p_network_write (int hook, char *buffer) { size_t result = 0, size = p_string_len(buffer); int length = (int)size; if (hook != pippolo_null_socket) { if (_p_endian_check() != pippolo_default_endian) pippolo_swap(length); if ((pippolo_intro == write(hook, &length, pippolo_intro))) { if ((result = write(hook, buffer, size))) pippolo_log(ELOG_COMMUNICATIONS, "writing message to token %d: %s", hook, buffer); } } return result; }
int _p_xml_draw (FILE *stream, str_xml_node *root, int deep) { int result = pippolo_true, index; struct str_xml_key *backup; struct str_xml_node *childrens; if (root) { if (p_string_len(root->label) > 0) { for (index = 0; index < deep; index++) fprintf(stream, "\t"); fprintf(stream, "<%s", root->label); backup = root->keys; while (backup) { fprintf(stream, " %s=%s", backup->key, backup->value); backup = backup->next; } fprintf(stream, ">"); } if (root->value) fprintf(stream, "%s", root->value); if (root->children) { childrens = root->children; fprintf(stream, "\n"); while (childrens) { if (!(result = _p_xml_draw(stream, childrens, deep+1))) break; childrens = childrens->next; } } if (p_string_len(root->label) > 0) { if ((root->children)) for (index = 0; index < deep; index++) fprintf(stream, "\t"); fprintf(stream, "</%s>", root->label); } } fprintf(stream, "\n"); return result; }
int _p_xml_string (char **string, str_xml_node *root) { int result = pippolo_true; struct str_xml_key *backup; struct str_xml_node *childrens; if (root) { if (p_string_len(root->label) > 0) { pippolo_append(*string, "<"); pippolo_append(*string, root->label); backup = root->keys; while (backup) { pippolo_append(*string, " "); pippolo_append(*string, backup->key); pippolo_append(*string, "="); pippolo_append(*string, backup->value); backup = backup->next; } pippolo_append(*string, ">"); } if (root->value) pippolo_append(*string, root->value); if (root->children) { childrens = root->children; while (childrens) { if (!(result = _p_xml_string(string, childrens))) break; childrens = childrens->next; } } if (p_string_len(root->label) > 0) { pippolo_append(*string, "</"); pippolo_append(*string, root->label); pippolo_append(*string, ">"); } } return result; }
void tims_cb_write(void *arg) { ClientSession_T *session = (ClientSession_T *)arg; int state = session->state; TRACE(TRACE_DEBUG, "[%p] state: [%d]", session, state); switch(state) { case CLIENTSTATE_QUIT_QUEUED: case CLIENTSTATE_QUIT: break; default: if (p_string_len(session->ci->write_buffer) > session->ci->write_buffer_offset) { ci_write(session->ci,NULL); break; } session->handle_input(session); break; } }
static void pop3_handle_input(void *arg) { char buffer[MAX_LINESIZE]; /* connection buffer */ ClientSession_T *session = (ClientSession_T *)arg; if (p_string_len(session->ci->write_buffer)) { ci_write(session->ci, NULL); return; } memset(buffer, 0, sizeof(buffer)); if (ci_readln(session->ci, buffer) == 0) return; ci_cork(session->ci); if (pop3(session, buffer) <= 0) { client_session_bailout(&session); return; } ci_uncork(session->ci); }
int _p_xml_analyze (struct str_xml_node **root, str_token_node *node, enum enum_xml_action action) { struct str_xml_node *current = *root, *singleton; struct str_token_node *key = NULL; int result = pippolo_true, passed; size_t length; enum enum_xml_action next = action; while (node) { passed = pippolo_false; if (node->token[0] == '<') { if (node->length > 1) { if ((node->token[1] == '/') || (node->token[1] == '?')) { next = EXML_ACTIONS_JUMP; passed = pippolo_true; } } else { next = EXML_ACTIONS_TITLE; passed = pippolo_true; } } else if (node->token[0] == '/') { if (node->length > 1) { if (node->token[1] == '>') { if (current) current = current->father; next = EXML_ACTIONS_CVALUE; passed = pippolo_true; } } } else if (node->token[0] == '>') { if (next == EXML_ACTIONS_JUMP) if (current) current = current->father; next = EXML_ACTIONS_CVALUE; passed = pippolo_true; } if ((!passed) && (action != EXML_ACTIONS_JUMP)) { switch (next) { case EXML_ACTIONS_TITLE: if (p_xml_node_allocate(&singleton)) { singleton->father = current; length = p_string_len(node->token)+1; if ((singleton->label = (char *) pippolo_malloc(length))) { snprintf(singleton->label, length, "%s", node->token); if ((*root)) { if (current) { if (current->children) singleton->next = current->children; current->children = singleton; } } else *root = singleton; current = singleton; } else pippolo_kill("out of memory, I'm dying bleaaargh"); } else pippolo_kill("out of memory, I'm dying bleaaargh"); next = EXML_ACTIONS_KEY; break; case EXML_ACTIONS_KEY: key = node; next = EXML_ACTIONS_KVALUE; break; case EXML_ACTIONS_KVALUE: if ((current) && (key)) { if (p_string_cmp(node->token, "=") != 0) { result = p_xml_key_append(&(current->keys), key->token, node->token); next = EXML_ACTIONS_KEY; key = NULL; } } break; case EXML_ACTIONS_CVALUE: if (current) pippolo_append(current->value, node->token); default: break; } } node = node->next; } return result; }
int tims_tokenizer(ClientSession_T *session, char *buffer) { int command_type = 0; char *command, *value = NULL; if (! session->command_type) { command = buffer; strip_crlf(command); g_strstrip(command); if (! strlen(command)) return FALSE; /* ignore empty commands */ value = strstr(command, " "); /* look for the separator */ if (value != NULL) { *value++ = '\0'; /* set a \0 on the command end and skip space */ if (strlen(value) == 0) value = NULL; /* no value specified */ } for (command_type = TIMS_LOUT; command_type < TIMS_END; command_type++) if (strcasecmp(command, commands[command_type]) == 0) break; /* commands that are allowed to have no arguments */ if ((value == NULL) && !(command_type <= TIMS_LIST) && (command_type < TIMS_END)) return tims_error(session, "NO \"This command requires an argument.\"\r\n"); TRACE (TRACE_DEBUG, "command [%s] value [%s]\n", command, value); session->command_type = command_type; } if (session->ci->rbuff_size) { size_t l = strlen(buffer); size_t n = min(session->ci->rbuff_size, l); p_string_append_len(session->rbuff, buffer, n); session->ci->rbuff_size -= n; if (! session->ci->rbuff_size) { String_T s = p_string_new(session->pool, p_string_str(session->rbuff)); session->args = p_list_append(session->args, s); p_string_printf(session->rbuff, "%s", ""); session->parser_state = TRUE; } TRACE(TRACE_DEBUG, "state [%d], size [%" PRIu64 "]", session->parser_state, session->ci->rbuff_size); return session->parser_state; } if (value) { char *s = value; int i = 0; char p = 0, c = 0; gboolean inquote = FALSE; String_T t = p_string_new(session->pool, ""); while ((c = s[i++])) { if (inquote) { if (c == '"' && p != '\\') { session->args = p_list_append(session->args, t); t = p_string_new(session->pool, ""); inquote = FALSE; } else { p_string_append_len(t, &c, 1); } p = c; continue; } if (c == '"' && p != '\\') { inquote = TRUE; p = c; continue; } if (c == ' ' && p != '\\') { p = c; continue; } if (c == '{') { // a literal... session->ci->rbuff_size = strtoull(s+i, NULL, 10); return FALSE; } p_string_append_len(t, &c, 1); p = c; } if (p_string_len(t)) { session->args = p_list_append(session->args, t); } else { p_string_free(t, TRUE); } } session->parser_state = TRUE; session->args = p_list_first(session->args); while (session->args) { String_T s = p_list_data(session->args); if (! s) break; TRACE(TRACE_DEBUG,"arg: [%s]", (char *)p_string_str(s)); if (! p_list_next(session->args)) break; session->args = p_list_next(session->args); } TRACE(TRACE_DEBUG, "[%p] cmd [%d], state [%d] [%s]", session, session->command_type, session->parser_state, buffer); return session->parser_state; }
void imap_handle_input(ImapSession *session) { char buffer[MAX_LINESIZE]; char *alloc_buf = NULL; uint64_t alloc_size = 0; int l, result; assert(session && session->ci && session->ci->write_buffer); // first flush the output buffer if (p_string_len(session->ci->write_buffer)) { TRACE(TRACE_DEBUG,"[%p] write buffer not empty", session); ci_write(session->ci, NULL); } // nothing left to handle if (p_string_len(session->ci->read_buffer) == 0) { TRACE(TRACE_DEBUG,"[%p] read buffer empty", session); return; } // command in progress if (session->command_state == FALSE && session->parser_state == TRUE) { TRACE(TRACE_DEBUG,"[%p] command in-progress", session); return; } // reset if we're done with the previous command if (session->command_state == TRUE) imap_session_reset(session); // Read in a line at a time if we don't have a string literal size defined // Otherwise read in rbuff_size amount of data while (TRUE) { char *input = NULL; FREE_ALLOC_BUF memset(buffer, 0, sizeof(buffer)); if (session->ci->rbuff_size <= 0) { l = ci_readln(session->ci, buffer); } else { alloc_size = session->ci->rbuff_size+1; alloc_buf = mempool_pop(session->pool, alloc_size); l = ci_read(session->ci, alloc_buf, session->ci->rbuff_size); } if (l == 0) break; // done if (session->error_count >= MAX_FAULTY_RESPONSES) { imap_session_printf(session, "* BYE [TRY RFC]\r\n"); imap_handle_abort(session); break; } // session is in a IDLE loop if (session->command_type == IMAP_COMM_IDLE && session->command_state == IDLE) { if (strlen(buffer) > 4 && strncasecmp(buffer,"DONE",4)==0) imap_session_printf(session, "%s OK IDLE terminated\r\n", session->tag); else imap_session_printf(session,"%s BAD Expecting DONE\r\n", session->tag); session->command_state = TRUE; // done imap_session_reset(session); continue; } if (alloc_buf != NULL) input = alloc_buf; else input = buffer; if (! imap4_tokenizer(session, input)) { FREE_ALLOC_BUF continue; } if ( session->parser_state < 0 ) { imap_session_printf(session, "%s BAD parse error\r\n", session->tag); imap_handle_retry(session); break; } if ( session->parser_state ) { result = imap4(session); TRACE(TRACE_DEBUG,"imap4 returned [%d]", result); if (result || (session->command_type == IMAP_COMM_IDLE && session->command_state == IDLE)) { imap_handle_exit(session, result); } break; } if (session->state == CLIENTSTATE_ERROR) { TRACE(TRACE_NOTICE, "session->state: ERROR. abort"); break; } }