static int auth_check(Octstr *user, Octstr *pass, List *headers, int *has_auth_hdr) { int i, res = -1; Octstr *v = http_header_value(headers, octstr_imm("Authorization")); Octstr *p = NULL, *q = NULL; *has_auth_hdr = (v != NULL); if (octstr_len(user) == 0) { res = 0; goto done; } if (!v || octstr_search(v, octstr_imm("Basic "), 0) != 0) goto done; p = octstr_copy(v, sizeof "Basic", octstr_len(v)); octstr_base64_to_binary(p); i = octstr_search_char(p, ':', 0); q = octstr_copy(p, i+1, octstr_len(p)); octstr_delete(p, i, octstr_len(p)); /* p = user, q = pass. */ if (octstr_compare(user, p) != 0 || octstr_compare(pass, q) != 0) res = -1; else res = 0; done: octstr_destroy(v); octstr_destroy(p); octstr_destroy(q); return res; }
static int cid_matches(List *headers, Octstr *start) { Octstr *cid = http_header_value(headers, octstr_imm("Content-ID")); char *cid_str; int cid_len; int ret; if (cid == NULL) return 0; /* First, strip the <> if any. XXX some mime coders produce such messiness! */ cid_str = octstr_get_cstr(cid); cid_len = octstr_len(cid); if (cid_str[0] == '<') { cid_str+=1; cid_len-=2; } if (start != NULL && cid != NULL && (octstr_compare(start, cid) == 0 || octstr_str_ncompare(start, cid_str, cid_len) == 0)) ret = 1; else ret = 0; octstr_destroy(cid); return ret; }
/* This function checks that there is a boundary parameter in the headers * for a multipart MIME object. If not, it is inserted and passed back to caller * in the variable boundary_elem. */ static void fix_boundary_element(List *headers, Octstr **boundary_elem) { Octstr *value, *boundary; long len; /* * Check if we have an boundary parameter already in the * Content-Type header. If no, add one, otherwise parse which one * we should use. * XXX this can be abstracted as function in gwlib/http.[ch]. */ value = http_header_value(headers, octstr_imm("Content-Type")); boundary = value ? http_get_header_parameter(value, octstr_imm("boundary")) : NULL; if (value == NULL) { /* we got here because it is multi-part, so... */ value = octstr_create("multipart/mixed"); http_header_add(headers, "Content-Type", "multipart/mixed"); } if (boundary == NULL) { Octstr *v; boundary = octstr_format("_boundary_%d_%ld_%c_%c_bd%d", random(), (long) time(NULL), 'A' + (random() % 26), 'a' + (random() % 26), random()); octstr_format_append(value, "; boundary=%S", boundary); http_header_remove_all(headers, "Content-Type"); http_header_add(headers, "Content-Type", octstr_get_cstr(value)); if ((v = http_header_value(headers, octstr_imm("MIME-Version"))) == NULL) http_header_add(headers, "MIME-Version", "1.0"); else octstr_destroy(v); } else if ((len = octstr_len(boundary)) > 0 && octstr_get_char(boundary, 0) == '"' && octstr_get_char(boundary, len - 1) == '"') { octstr_delete(boundary, 0, 1); octstr_delete(boundary, len - 2, 1); } octstr_destroy(value); if (boundary_elem) *boundary_elem = boundary; else octstr_destroy(boundary); }
static void mime_entity_dump_real(MIMEEntity *m, unsigned int level) { long i, items; Octstr *prefix, *type, *charset; Octstr *tmp; unsigned int j; gw_assert(m != NULL && m->headers != NULL); prefix = octstr_create(""); for (j = 0; j < level * 2; j++) octstr_append_cstr(prefix, " "); http_header_get_content_type(m->headers, &type, &charset); debug("mime.dump",0,"%sContent-Type `%s'", octstr_get_cstr(prefix), octstr_get_cstr(type)); for(i = 0; i < gwlist_len(m->headers); i++) { tmp = gwlist_get(m->headers,i); debug("mime.dump",0, "Header: %s", octstr_get_cstr(tmp)); } if (m->start != NULL) { Octstr *cid = http_header_value(m->start->headers, octstr_imm("Content-ID")); debug("mime.dump",0,"%sRelated to Content-ID <%s> MIMEEntity at address `%p'", octstr_get_cstr(prefix), octstr_get_cstr(cid), m->start); octstr_destroy(cid); } items = gwlist_len(m->multiparts); debug("mime.dump",0,"%sBody contains %ld MIME entities, size %ld", octstr_get_cstr(prefix), items, (items == 0 && m->body) ? octstr_len(m->body) : -1); octstr_destroy(prefix); octstr_destroy(type); octstr_destroy(charset); for (i = 0; i < items; i++) { MIMEEntity *e = gwlist_get(m->multiparts, i); mime_entity_dump_real(e, level + 1); } }
/* Returns (copy of) the 'start' element of a multi-part entity. */ MIMEEntity *mime_multipart_start_elem(MIMEEntity *e) { gw_assert(e != NULL); /* If e->start element is not yet set, set it as follows: * - if content type is not set, then set it to NULL * - if the start element is not set but this is a multipart object, set * it to first multipart element, else set it to null * - if the start element of the content type is set, find a matching object * and set e->start accordingly. * Finally, return a copy of it. */ if (!e->start) { Octstr *ctype = http_header_value(e->headers, octstr_imm("Content-Type")); Octstr *start = get_start_param(ctype); int i; if (!ctype) e->start = NULL; else if (!start) { if (gwlist_len(e->multiparts) > 0) e->start = gwlist_get(e->multiparts, 0); else e->start = NULL; } else for (i = 0; i < gwlist_len(e->multiparts); i++) { MIMEEntity *x = gwlist_get(e->multiparts, i); if (cid_matches(x->headers, start)) { e->start = x; break; } } if (ctype) octstr_destroy(ctype); if (start) octstr_destroy(start); } return (e->start) ? mime_entity_duplicate(e->start) : NULL; }
static void client_thread(void *arg) { HTTPClient *client; Octstr *body, *url, *ip; List *headers, *resph, *cgivars; HTTPCGIVar *v; Octstr *reply_body, *reply_type; unsigned long n = 0; int status, i; while (run) { client = http_accept_request(port, &ip, &url, &headers, &body, &cgivars); n++; if (client == NULL) break; info(0, "Request for <%s> from <%s>", octstr_get_cstr(url), octstr_get_cstr(ip)); if (verbose) debug("test.http", 0, "CGI vars were"); /* * Don't use gwlist_extract() here, otherwise we don't have a chance * to re-use the cgivars later on. */ for (i = 0; i < gwlist_len(cgivars); i++) { if ((v = gwlist_get(cgivars, i)) != NULL && verbose) { octstr_dump(v->name, 0); octstr_dump(v->value, 0); } } if (arg == NULL) { reply_body = octstr_duplicate(reply_text); reply_type = octstr_create("Content-Type: text/plain; " "charset=\"UTF-8\""); } else { reply_body = octstr_duplicate(arg); reply_type = octstr_create("Content-Type: text/vnd.wap.wml"); } resph = gwlist_create(); gwlist_append(resph, reply_type); status = HTTP_OK; /* check for special URIs and handle those */ if (octstr_compare(url, octstr_imm("/quit")) == 0) { run = 0; } else if (octstr_compare(url, octstr_imm("/whitelist")) == 0) { octstr_destroy(reply_body); if (whitelist != NULL) { if (verbose) { debug("test.http.server", 0, "we send a white list"); octstr_dump(whitelist, 0); } reply_body = octstr_duplicate(whitelist); } else { reply_body = octstr_imm(""); } } else if (octstr_compare(url, octstr_imm("/blacklist")) == 0) { octstr_destroy(reply_body); if (blacklist != NULL) { if (verbose) { debug("test.http.server", 0, "we send a blacklist"); octstr_dump(blacklist, 0); } reply_body = octstr_duplicate(blacklist); } else { reply_body = octstr_imm(""); } } else if (octstr_compare(url, octstr_imm("/save")) == 0) { /* safe the body into a temporary file */ pid_t pid = getpid(); FILE *f = fopen(octstr_get_cstr(octstr_format("/tmp/body.%ld.%ld", pid, n)), "w"); octstr_print(f, body); fclose(f); } else if (octstr_compare(url, octstr_imm("/redirect/")) == 0) { /* provide us with a HTTP 302 redirection response * will return /redirect/<pid> for the location header * and will return /redirect/ if cgivar loop is set to allow looping */ Octstr *redirect_header, *scheme, *uri, *l; pid_t pid = getpid(); uri = ((l = http_cgi_variable(cgivars, "loop")) != NULL) ? octstr_format("%s?loop=%s", octstr_get_cstr(url), octstr_get_cstr(l)) : octstr_format("%s%ld", octstr_get_cstr(url), pid); octstr_destroy(reply_body); reply_body = octstr_imm("Here you got a redirection URL that you should follow."); scheme = ssl ? octstr_imm("https://") : octstr_imm("http://"); redirect_header = octstr_format("Location: %s%s%s", octstr_get_cstr(scheme), octstr_get_cstr(http_header_value(headers, octstr_imm("Host"))), octstr_get_cstr(uri)); gwlist_append(resph, redirect_header); status = HTTP_FOUND; /* will provide 302 */ octstr_destroy(uri); } else if (octstr_compare(url, octstr_imm("/mmsc")) == 0) { /* fake a M-Send.conf PDU which is using MMSEncapsulation as body */ pid_t pid = getpid(); FILE *f; gwlist_destroy(resph, octstr_destroy_item); octstr_destroy(reply_body); reply_type = octstr_create("Content-Type: application/vnd.wap.mms-message"); reply_body = octstr_create(""); octstr_append_from_hex(reply_body, "8c81" /* X-Mms-Message-Type: m-send-conf */ "98632d3862343300" /* X-Mms-Transaction-ID: c-8b43 */ "8d90" /* X-Mms-MMS-Version: 1.0 */ "9280" /* Response-status: Ok */ "8b313331373939353434393639383434313731323400" ); /* Message-Id: 13179954496984417124 */ resph = gwlist_create(); gwlist_append(resph, reply_type); /* safe the M-Send.req body into a temporary file */ f = fopen(octstr_get_cstr(octstr_format("/tmp/mms-body.%ld.%ld", pid, n)), "w"); octstr_print(f, body); fclose(f); } if (verbose) { debug("test.http", 0, "request headers were"); http_header_dump(headers); if (body != NULL) { debug("test.http", 0, "request body was"); octstr_dump(body, 0); } } if (extra_headers != NULL) http_header_combine(resph, extra_headers); /* return response to client */ http_send_reply(client, status, resph, reply_body); octstr_destroy(ip); octstr_destroy(url); octstr_destroy(body); octstr_destroy(reply_body); http_destroy_cgiargs(cgivars); gwlist_destroy(headers, octstr_destroy_item); gwlist_destroy(resph, octstr_destroy_item); } octstr_destroy(whitelist); octstr_destroy(blacklist); debug("test.http", 0, "Working thread 'client_thread' terminates"); http_close_all_ports(); }
void mmsc_receive_func(MmscGrp *m) { int i; MmsBoxHTTPClientInfo h = {NULL}; List *mmsc_incoming_reqs = gwlist_create(); long *thids = gw_malloc((maxthreads + 1)*sizeof thids[0]); gwlist_add_producer(mmsc_incoming_reqs); for (i = 0; i<maxthreads; i++) thids[i] = gwthread_create((gwthread_func_t *)dispatch_mm7_recv, mmsc_incoming_reqs); h.m = m; while(rstop == 0 && (h.client = http_accept_request(m->incoming.port, &h.ip, &h.url, &h.headers, &h.body, &h.cgivars)) != NULL) if (is_allowed_ip(m->incoming.allow_ip, m->incoming.deny_ip, h.ip)) { MmsBoxHTTPClientInfo *hx = gw_malloc(sizeof hx[0]); h.ua = http_header_value(h.headers, octstr_imm("User-Agent")); *hx = h; debug("mmsbox", 0, " MM7 Incoming, IP=[%s], MMSC=[%s], dest_port=[%ld] ", h.ip ? octstr_get_cstr(h.ip) : "", octstr_get_cstr(m->id), m->incoming.port); /* Dump headers, url etc. */ #if 0 http_header_dump(h.headers); if (h.body) octstr_dump(h.body, 0); if (h.ip) octstr_dump(h.ip, 0); #endif gwlist_produce(mmsc_incoming_reqs, hx); } else { h.ua = http_header_value(h.headers, octstr_imm("User-Agent")); mms_error_ex("auth",0, "MM7", m->id, "HTTP: Incoming IP denied MMSC[%s] ip=[%s], ua=[%s], disconnected", m->id ? octstr_get_cstr(m->id) : "(none)", h.ip ? octstr_get_cstr(h.ip) : "(none)", h.ua ? octstr_get_cstr(h.ua) : "(none)"); http_send_reply(h.client, HTTP_FORBIDDEN, NULL, octstr_imm("Access denied.")); free_mmsbox_http_clientInfo(&h, 0); } debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down...", octstr_get_cstr(m->id)); gwlist_remove_producer(mmsc_incoming_reqs); for (i = 0; i<maxthreads; i++) if (thids[i] >= 0) gwthread_join(thids[i]); gwlist_destroy(mmsc_incoming_reqs, NULL); gw_free(thids); debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down complete.", octstr_get_cstr(m->id)); }
static int mm7http_receive(MmsBoxHTTPClientInfo *h) { MmsMsg *m = NULL; List *mh = NULL; int hstatus = HTTP_OK; List *rh = http_create_empty_headers(); Octstr *reply_body = NULL; List *to = NULL; Octstr *hto = NULL, *subject = NULL, *msgid = NULL; Octstr *hfrom = NULL, *body, *rr_uri = NULL, *dlr_uri = NULL; time_t expiryt = -1, deliveryt = -1; Octstr *qf = NULL, *mmc_id = NULL, *qdir = NULL, *s; int msize; int dlr, rr; int mtype; List *cgivars_ctypes = NULL, *rqh = http_create_empty_headers(); parse_cgivars(h->headers, h->body, &h->cgivars, &cgivars_ctypes); hfrom = http_cgi_variable(h->cgivars, "from"); hto = http_cgi_variable(h->cgivars, "to"); body = http_cgi_variable(h->cgivars, "mms"); msize = octstr_len(body); debug("mmsbox.mm7http.sendinterface", 0, " --> Enterred http-mmsc send interface, blen=[%d] <--- ", msize); if (hto == NULL) { http_header_add(rh, "Content-Type", "text/plain"); hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Missing 'to' argument"); goto done; } else if (hfrom == NULL) { http_header_add(rh, "Content-Type", "text/plain"); hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Missing 'from' argument"); goto done; } else if (body == NULL || /* A message is required, and must parse */ (m = mms_frombinary(body, hfrom ? hfrom : octstr_imm("anon@anon"))) == NULL) { http_header_add(rh, "Content-Type", "text/plain"); hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Unexpected MMS message, no content?"); goto done; } to = octstr_split_words(hto); mtype = mms_messagetype(m); mh = mms_message_headers(m); /* find interesting headers. */ subject = http_header_value(mh, octstr_imm("Subject")); /* Find expiry and delivery times */ if ((s = http_header_value(mh, octstr_imm("X-Mms-Expiry"))) != NULL) { expiryt = date_parse_http(s); octstr_destroy(s); } else expiryt = time(NULL) + DEFAULT_EXPIRE; if ((s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time"))) != NULL) { deliveryt = date_parse_http(s); octstr_destroy(s); } else deliveryt = 0; qdir = get_mmsbox_queue_dir(hfrom, to, h->m, &mmc_id); /* get routing info. */ switch(mtype) { Octstr *value, *value2; case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: /* Get/make a Message ID */ if ((msgid = mms_get_header_value(m, octstr_imm("Message-ID"))) == NULL) { /* Make a message id for it directly. We need it below. */ msgid = mms_make_msgid(NULL, NULL); mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid)); } if ((value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"))) != NULL && octstr_case_compare(value, octstr_imm("Yes")) == 0) dlr = 1; else dlr = 0; octstr_destroy(value); if ((value = http_header_value(mh, octstr_imm("X-Mms-Read-Report"))) != NULL && octstr_case_compare(value, octstr_imm("Yes")) == 0) rr = 1; else rr = 0; octstr_destroy(value); if (deliveryt < 0) deliveryt = time(NULL); if (expiryt < 0) expiryt = time(NULL) + DEFAULT_EXPIRE; mms_remove_headers(m, "Bcc"); mms_remove_headers(m, "X-Mms-Delivery-Time"); mms_remove_headers(m, "X-Mms-Expiry"); mms_remove_headers(m, "X-Mms-Sender-Visibility"); MOD_SUBJECT(m, h->m, hfrom); if (qdir == outgoing_qdir) { /* We need to remember the old message ID so we can re-write it * if a DLR is relayed backwards. */ Octstr *t = mms_maketransid(NULL, octstr_imm(MM_NAME)); /* make a fake transaction id so dlr works*/ http_header_add(rqh, "X-Mbuni-TransactionID", octstr_get_cstr(t)); if (dlr) dlr_uri = octstr_format("msgid:%S", msgid); if (rr) rr_uri = octstr_format("msgid:%S", msgid); octstr_destroy(t); } /* Save it, put message id in header, return. */ qf = qfs->mms_queue_add(hfrom, to, subject, h->m->id, mmc_id, deliveryt, expiryt, m, NULL, NULL, NULL, dlr_uri, rr_uri, rqh, dlr, octstr_get_cstr(qdir), "MM7/HTTP-IN", NULL); if (qf) { /* Log to access log */ mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_OK; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; break; case MMS_MSGTYPE_DELIVERY_IND: msgid = mms_get_header_value(m, octstr_imm("Message-ID")); value = mms_get_header_value(m, octstr_imm("X-Mms-Status")); value2 = mms_get_header_value(m, octstr_imm("X-Mbuni-Orig-Message-ID")); rr_uri = mmsbox_get_report_info(m, h->m, mmc_id, "delivery-report", value, rqh, NULL, 0, msgid); if (mmc_id == NULL && value2) http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2)); qf = qfs->mms_queue_add(hfrom, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, NULL, NULL, rr_uri, NULL, rqh, 0, octstr_get_cstr(qdir), "MM7/HTTP-IN", NULL); if (qf) { /* Log to access log */ mms_log("DeliveryReport", hfrom, to, -1, msgid,value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_OK; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; octstr_destroy(value); octstr_destroy(value2); break; case MMS_MSGTYPE_READ_ORIG_IND: msgid = mms_get_header_value(m, octstr_imm("Message-ID")); value = mms_get_header_value(m, octstr_imm("X-Mms-Read-Status")); value2 = mms_get_header_value(m, octstr_imm("X-Mbuni-Orig-Message-ID")); rr_uri = mmsbox_get_report_info(m, h->m, mmc_id, "read-report", value, rqh, NULL, 0, msgid); if (mmc_id == NULL && value2) http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2)); qf = qfs->mms_queue_add(hfrom, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, NULL, NULL, rr_uri, NULL, rqh, 0, octstr_get_cstr(qdir), "MM7/HTTP-IN", NULL); if (qf) { /* Log to access log */ mms_log("Received RR", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_NO_CONTENT; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; octstr_destroy(value); octstr_destroy(value2); break; } done: http_header_add(rh, "X-Mbuni-Version", VERSION); http_send_reply(h->client, hstatus, rh, msgid ? msgid : (qf ? qf : octstr_imm(""))); gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); octstr_destroy(subject); octstr_destroy(qf); octstr_destroy(mmc_id); octstr_destroy(msgid); http_destroy_headers(mh); http_destroy_headers(rh); http_destroy_headers(rqh); if (m) mms_destroy(m); http_destroy_cgiargs(cgivars_ctypes); return http_status_class(hstatus) == HTTP_STATUS_SUCCESSFUL ? 0 : -1; }
static int mm7eaif_receive(MmsBoxHTTPClientInfo *h) { MmsMsg *m = NULL; List *mh = NULL; int hstatus = HTTP_NO_CONTENT; List *rh = http_create_empty_headers(); List *rqh = http_create_empty_headers(); Octstr *reply_body = NULL, *value = NULL, *value2 = NULL; List *to = gwlist_create(), *hto = NULL; Octstr *subject = NULL, *otransid = NULL, *msgid = NULL; Octstr *hfrom = NULL, *rr_uri = NULL; time_t expiryt = -1, deliveryt = -1; Octstr *qf = NULL, *xver = NULL, *mmc_id = NULL, *qdir = NULL; int msize = h->body ? octstr_len(h->body) : 0; int dlr; int mtype; debug("mmsbox.mm7eaif.sendinterface", 0, " --> Enterred eaif send interface, blen=[%d] <--- ", msize); hfrom = http_header_value(h->headers, octstr_imm("X-NOKIA-MMSC-From")); if (!h->body || /* A body is required, and must parse */ (m = mms_frombinary(h->body, hfrom ? hfrom : octstr_imm("anon@anon"))) == NULL) { http_header_add(rh, "Content-Type", "text/plain"); hstatus = HTTP_BAD_REQUEST; reply_body = octstr_format("Unexpected MMS message, no body?"); goto done; } /* XXXX handle delivery reports differently. */ mtype = mms_messagetype(m); mh = mms_message_headers(m); /* Now get sender and receiver data. * for now we ignore adaptation flags. */ mms_collect_envdata_from_msgheaders(mh, &to, &subject, &otransid, &expiryt, &deliveryt, DEFAULT_EXPIRE, -1, octstr_get_cstr(unified_prefix), strip_prefixes); if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL && gwlist_len(hto) > 0) { /* To address is in headers. */ int i, n; gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); to = gwlist_create(); for (i = 0, n = gwlist_len(hto); i < n; i++) { Octstr *h = NULL, *v = NULL; List *l; void *x; http_header_get(hto,i, &h, &v); l = http_header_split_value(v); while ((x = gwlist_extract_first(l)) != NULL) gwlist_append(to, x); gwlist_destroy(l, NULL); octstr_destroy(h); octstr_destroy(v); } } qdir = get_mmsbox_queue_dir(hfrom, to, h->m, &mmc_id); /* get routing info. */ switch(mtype) { case MMS_MSGTYPE_SEND_REQ: case MMS_MSGTYPE_RETRIEVE_CONF: /* Get Message ID */ if ((msgid = http_header_value(h->headers, octstr_imm("X-NOKIA-MMSC-Message-Id"))) == NULL) msgid = http_header_value(mh, octstr_imm("Message-ID")); else mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid)); /* replace it in the message.*/ value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report")); if (value && octstr_case_compare(value, octstr_imm("Yes")) == 0) dlr = 1; else dlr = 0; if (deliveryt < 0) deliveryt = time(NULL); if (expiryt < 0) expiryt = time(NULL) + DEFAULT_EXPIRE; if (hfrom == NULL) hfrom = http_header_value(mh, octstr_imm("From")); mms_remove_headers(m, "Bcc"); mms_remove_headers(m, "X-Mms-Delivery-Time"); mms_remove_headers(m, "X-Mms-Expiry"); mms_remove_headers(m, "X-Mms-Sender-Visibility"); MOD_SUBJECT(m, h->m, hfrom); /* Save it, put message id in header, return. */ qf = qfs->mms_queue_add(hfrom, to, subject, h->m->id, mmc_id, deliveryt, expiryt, m, NULL, NULL, NULL, NULL, NULL, NULL, dlr, octstr_get_cstr(qdir), "MM7/EAIF-IN", NULL); if (qf) { /* Log to access log */ mms_log("Received", hfrom, to, msize, msgid, NULL, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_NO_CONTENT; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; octstr_destroy(value); octstr_destroy(value2); break; case MMS_MSGTYPE_DELIVERY_IND: msgid = mms_get_header_value(m, octstr_imm("Message-ID")); value = mms_get_header_value(m, octstr_imm("X-Mms-Status")); value2 = mms_get_header_value(m, octstr_imm("X-Mbuni-Orig-Message-ID")); rr_uri = mmsbox_get_report_info(m, h->m, mmc_id, "delivery-report", value, rqh, NULL, 0, msgid); if (value2 && mmc_id == NULL) http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2)); qf = qfs->mms_queue_add(hfrom, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, NULL, NULL, rr_uri, NULL, rqh, 0, octstr_get_cstr(qdir), "MM7/EAIF-IN", NULL); if (qf) { /* Log to access log */ mms_log("DeliveryReport", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_NO_CONTENT; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; octstr_destroy(value); octstr_destroy(value2); break; case MMS_MSGTYPE_READ_ORIG_IND: msgid = mms_get_header_value(m, octstr_imm("Message-ID")); value = mms_get_header_value(m, octstr_imm("X-Mms-Read-Status")); value2 = mms_get_header_value(m, octstr_imm("X-Mbuni-Orig-Message-ID")); rr_uri = mmsbox_get_report_info(m, h->m, mmc_id, "read-report", value, rqh, NULL, 0, msgid); if (value2 && mmc_id == NULL) http_header_add(rqh, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value2)); qf = qfs->mms_queue_add(hfrom, to, NULL, h->m->id, mmc_id, 0, time(NULL) + default_msgexpiry, m, NULL, NULL, NULL, rr_uri, NULL, rqh, 0, octstr_get_cstr(qdir), "MM7/EAIF-IN", NULL); if (qf) { /* Log to access log */ mms_log("Received RR", hfrom, to, -1, msgid, value, h->m->id, "MMSBox", h->ua, NULL); hstatus = HTTP_NO_CONTENT; } else hstatus = HTTP_INTERNAL_SERVER_ERROR; octstr_destroy(value); octstr_destroy(value2); break; } done: xver = octstr_format(EAIF_VERSION, h->m->ver.major, h->m->ver.minor1); http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver)); octstr_destroy(xver); http_send_reply(h->client, hstatus, rh, octstr_imm("")); http_destroy_headers(hto); http_destroy_headers(rqh); gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy); octstr_destroy(hfrom); octstr_destroy(subject); octstr_destroy(otransid); octstr_destroy(msgid); octstr_destroy(qf); octstr_destroy(mmc_id); octstr_destroy(rr_uri); http_destroy_headers(mh); mms_destroy(m); return http_status_class(hstatus) == HTTP_STATUS_SUCCESSFUL ? 0 : -1; }
static int sendMsg(MmsEnvelope *e) { MmsMsg *msg = NULL; int i, n; Octstr *otransid = e->hdrs ? http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL; if ((msg = qfs->mms_queue_getdata(e)) == NULL) { mms_error(0, "MM7", NULL, "MMSBox queue error: Failed to load message for queue id [%s]!", e->xqfname); goto done2; } for (i = 0, n = gwlist_len(e->to); i<n; i++) { int res = MMS_SEND_OK; MmsEnvelopeTo *to = gwlist_get(e->to, i); Octstr *err = NULL; time_t tnow = time(NULL); MmscGrp *mmc = NULL; Octstr *new_msgid = NULL; List *errl = NULL; int is_email = 0; if (!to || !to->process) continue; if (e->expiryt != 0 && /* Handle message expiry. */ e->expiryt < tnow) { err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt); res = MMS_SEND_ERROR_FATAL; goto done; } else if (e->attempts >= maxsendattempts) { err = octstr_format("MMSBox error: Failed to deliver to " "%S after %ld attempts. (max attempts allowed is %ld)!", to->rcpt, e->attempts, maxsendattempts); res = MMS_SEND_ERROR_FATAL; goto done; } is_email = (octstr_search_char(to->rcpt, '@', 0) > 0); if ((mmc = get_handler_mmc(e->viaproxy, to->rcpt, e->from)) == NULL && !is_email) { err = octstr_format("MMSBox error: Failed to deliver to " "%S. Don't know how to route!", to->rcpt); res = MMS_SEND_ERROR_TRANSIENT; goto done; } if (is_email) { int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0); int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0); int len = octstr_len(e->from); Octstr *pfrom; if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) pfrom = octstr_copy(e->from, 0, j); else if (k > 0 && k + sizeof "/TYPE=IPv" == len) pfrom = octstr_copy(e->from, 0, k); else pfrom = octstr_duplicate(e->from); if (octstr_search_char(e->from, '@', 0) < 0) octstr_format_append(pfrom,"@%S", myhostname); res = mms_sendtoemail(pfrom, to->rcpt, e->subject ? e->subject : octstr_imm(""), e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd), myhostname, 0, 0, "", "", 0, e->xqfname, e->hdrs); octstr_destroy(pfrom); } else { res = mms_sendtommsc(mmc, e, to->rcpt, otransid, msg, &new_msgid, &errl); if (errl) err = http_header_value(errl, octstr_imm("X-Mbuni-Error")); } if (mmc) { if (res == MMS_SEND_OK) mmc->mt_pdus++; else mmc->mt_errors++; mmc->last_pdu = time(NULL); return_mmsc_conn(mmc); /* important. */ } done: if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) { to->process = 0; if (e->msgtype == MMS_MSGTYPE_SEND_REQ || e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */ queue_dlr(mmc, e->from, to->rcpt, new_msgid, octstr_imm("Forwarded"), "MM7-Out", errl); } else if (res == MMS_SEND_ERROR_FATAL && mmc) { if (e->msgtype == MMS_MSGTYPE_SEND_REQ || e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */ queue_dlr(mmc, e->from, to->rcpt, e->msgId, (e->expiryt != 0 && e->expiryt < tnow) ? octstr_imm("Expired") : octstr_imm("Rejected"), "MM7-Out", errl); } if (res == MMS_SEND_ERROR_FATAL) to->process = 0; /* No more attempts. */ /* handle CDR */ if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED || res == MMS_SEND_ERROR_FATAL) { Octstr *mclass = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class")); Octstr *prio = mms_get_header_value(msg, octstr_imm("X-Mms-Priority")); Octstr *mstatus = mms_get_header_value(msg, octstr_imm("X-Mms-Status")); /* Do CDR */ cdrfs->logcdr(e->created, octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), octstr_get_cstr(e->msgId), mmc ? octstr_get_cstr(mmc->id) : NULL, /* Should we touch mmc here? XXX */ e->src_interface, "MM7", e->msize, (char *)mms_message_type_to_cstr(e->msgtype), prio ? octstr_get_cstr(prio) : NULL, mclass ? octstr_get_cstr(mclass) : NULL, res == MMS_SEND_ERROR_FATAL ? "dropped" : (mstatus ? octstr_get_cstr(mstatus) : "sent"), e->dlr, 0); octstr_destroy(mclass); octstr_destroy(prio); octstr_destroy(mstatus); } if (err == NULL) mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]", SEND_ERROR_STR(res), octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize, new_msgid ? octstr_get_cstr(new_msgid) : "N/A"); else mms_error_ex("MT", 0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: %s", SEND_ERROR_STR(res), octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize, octstr_get_cstr(err)); octstr_destroy(new_msgid); octstr_destroy(err); http_destroy_headers(errl); e->lasttry = tnow; if (qfs->mms_queue_update(e) == 1) { e = NULL; break; /* Queue entry gone. */ } } done2: mms_destroy(msg); octstr_destroy(otransid); if (e) { /* Update the queue if it is still valid (e.g. recipients not handled) * XXX can this happen here??... */ e->lasttry = time(NULL); e->attempts++; /* Update count of number of delivery attempts. */ e->sendt = e->lasttry + mmsbox_send_back_off * e->attempts; if (qfs->mms_queue_update(e) != 1) qfs->mms_queue_free_env(e); } return 1; /* always delete queue entry. */ }
static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *transid, char *vasid, List *hdrs, MmsMsg *m, Octstr **error, int *retry) { Octstr *ret = NULL, *resp = NULL; int mtype = mms_messagetype(m); int hstatus = HTTP_OK; List *rh = http_create_empty_headers(), *ph = NULL; Octstr *body = NULL, *rbody = NULL, *xver = NULL; char *msgtype; mms_info(0, "MM7", mmc->id, "MMSBox: Send [eaif] to MMC[%s], msg type [%s], from %s, to %s", mmc ? octstr_get_cstr(mmc->id) : "", mms_message_type_to_cstr(mtype), octstr_get_cstr(from), octstr_get_cstr(to)); http_header_remove_all(rh, "X-Mms-Allow-Adaptations"); http_header_add(rh, "X-NOKIA-MMSC-To", octstr_get_cstr(to)); http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from)); xver = octstr_format(EAIF_VERSION, mmc->ver.major, mmc->ver.minor1); http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver)); octstr_destroy(xver); if (mtype == MMS_MSGTYPE_SEND_REQ || mtype == MMS_MSGTYPE_RETRIEVE_CONF) { msgtype = "MultiMediaMessage"; mms_make_sendreq(m); /* ensure it is a sendreq. */ } else if (mtype == MMS_MSGTYPE_DELIVERY_IND) msgtype = "DeliveryReport"; else msgtype = "ReadReply"; http_header_add(rh, "X-NOKIA-MMSC-Message-Type", msgtype); if (hdrs) http_header_combine(rh, hdrs); /* If specified, then update and pass on. */ http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message"); /* Patch the message FROM and TO fields. */ mms_replace_header_value(m, "From", octstr_get_cstr(from)); mms_replace_header_value(m, "To", octstr_get_cstr(to)); mms_replace_header_value(m,"X-Mms-Transaction-ID", transid ? octstr_get_cstr(transid) : "000"); body = mms_tobinary(m); hstatus = mmsbox_url_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph, &rbody); if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) { *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status = %d !", mmc->mmsc_url, hstatus); } else { MmsMsg *mresp = rbody ? mms_frombinary(rbody, octstr_imm("anon@anon")) : NULL; resp = octstr_imm("Ok"); if (mresp && mms_messagetype(mresp) == MMS_MSGTYPE_SEND_CONF) resp = mms_get_header_value(mresp, octstr_imm("X-Mms-Response-Status")); if (octstr_case_compare(resp, octstr_imm("ok")) != 0) hstatus = HTTP_STATUS_SERVER_ERROR; /* error. */ else if (mresp) ret = mms_get_header_value(mresp, octstr_imm("Message-ID")); mms_destroy(mresp); } if (hstatus < 0) ret = NULL; else { hstatus = http_status_class(hstatus); if (hstatus == HTTP_STATUS_SERVER_ERROR || hstatus == HTTP_STATUS_CLIENT_ERROR) ret = NULL; else if (!ret) ret = http_header_value(ph, octstr_imm("X-Nokia-MMSC-Message-Id")); } *retry = (ret == NULL && (hstatus == HTTP_STATUS_SERVER_ERROR || hstatus < 0)); if (ret) mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL); #if 0 mms_info(0, "MM7", mmc->id,"Sent to MMC[%s], code=[%d], resp=[%s] msgid [%s]", octstr_get_cstr(mmc->id), hstatus, resp ? octstr_get_cstr(resp) : "(none)", ret ? octstr_get_cstr(ret) : "(none)"); #endif http_destroy_headers(rh); octstr_destroy(body); http_destroy_headers(ph); octstr_destroy(rbody); octstr_destroy(resp); return ret; }
int create_web_data(char *p_pszFileName, char *p_pszMMSDir, const char *p_pszWebDir) { int iRetVal = 0; MmsEnvelope *psoEnv; MmsMsg *psoMsg = NULL; List *psoHdrList = NULL; Octstr *psoHdrs = NULL, *psoHdrName = NULL, *psoHdrValue = NULL, *psoWebDir = NULL; MIMEEntity *psoMIME, *psoMIMETmp; int iMIMENum, iMIMEInd; int iFile = -1; gwlib_init(); mms_strings_init(); /* формируем имя директрии для вывода результатов */ psoWebDir = octstr_create(p_pszWebDir); if('/' != octstr_get_char(psoWebDir, octstr_len(psoWebDir) - 1)) { octstr_append_char(psoWebDir, '/'); } octstr_append_cstr(psoWebDir, p_pszFileName); /* создаем директорию */ if(mkdir(octstr_get_cstr(psoWebDir), 0777)) { if(errno != EEXIST) { iRetVal = 2; } goto done; } psoEnv = default_qfuncs.mms_queue_readenvelope(p_pszFileName, p_pszMMSDir, 0); if(psoEnv) { psoMsg = default_qfuncs.mms_queue_getdata(psoEnv); default_qfuncs.mms_queue_free_env(psoEnv); } else { iRetVal = 3; goto done; } if(!psoMsg) { iRetVal = 4; goto done; } psoHdrs = octstr_create(""); /* выбираем необходимые заголовки */ psoHdrList = mms_message_headers(psoMsg); /* From */ psoHdrName = octstr_create("From"); psoHdrValue = http_header_value(psoHdrList, psoHdrName); octstr_format_append(psoHdrs, "%S/%S\r\n", psoHdrName, psoHdrValue); octstr_truncate(psoHdrName, 0); /* To */ octstr_append_cstr(psoHdrName, "To"); psoHdrValue = http_header_value(psoHdrList, psoHdrName); octstr_format_append(psoHdrs, "%S/%S\r\n", psoHdrName, psoHdrValue); octstr_truncate(psoHdrName, 0); /* Date */ octstr_append_cstr(psoHdrName, "Date"); psoHdrValue = http_header_value(psoHdrList, psoHdrName); octstr_format_append(psoHdrs, "%S/%S", psoHdrName, psoHdrValue); octstr_truncate(psoHdrName, 0); /**/ psoMIME = mms_tomime(psoMsg, 1); iMIMENum = mime_entity_num_parts(psoMIME); if(psoMIME) { for(iMIMEInd = 0; iMIMEInd < iMIMENum; ++iMIMEInd) { psoMIMETmp = mime_entity_get_part(psoMIME, iMIMEInd); operate_single_mime(psoHdrs, psoMIMETmp, octstr_get_cstr(psoWebDir)); } } /* формируем имя файла для вывода результатов, используем ту же переменную, что и для директории */ if('/' != octstr_get_char(psoWebDir, octstr_len(psoWebDir) - 1)) { octstr_append_char(psoWebDir, '/'); } octstr_append_cstr(psoWebDir, "common"); /* создаем файл */ iFile = open(octstr_get_cstr(psoWebDir), O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(0 < iFile) { if(octstr_len(psoHdrs) != write(iFile, octstr_get_cstr(psoHdrs), octstr_len(psoHdrs))) { iRetVal = 5; } close(iFile); } else { if(errno != EEXIST) { iRetVal = 6; } } done: if(psoHdrs) { octstr_destroy(psoHdrs); } if(psoHdrName) { octstr_destroy(psoHdrName); } if(psoWebDir) { octstr_destroy(psoWebDir); } mms_strings_shutdown(); gwlib_shutdown(); return iRetVal; }
int operate_single_mime(Octstr *p_psoHdrs, MIMEEntity *p_psoMIME, const char *p_pszWebDir) { int iRetVal = 0; Octstr *psoHdrName = NULL, *psoHdrValue = NULL; Octstr *psoMIMEOStr = NULL, *psoFileName = NULL; List *psoHdrList = NULL; int iFile = -1; if(psoMIMEOStr) { octstr_destroy(psoMIMEOStr); } /* выбираем необходимые заголовки */ psoHdrList = mime_entity_headers(p_psoMIME); /* Content-type */ psoHdrName = octstr_create("Content-type"); psoHdrValue = http_header_value(psoHdrList, psoHdrName); if(0 == strncasecmp("application/smil", octstr_get_cstr(psoHdrValue), 16)) { goto done; } octstr_format_append(p_psoHdrs, "\r\n"); octstr_format_append(p_psoHdrs, "\r\n%S;%S", psoHdrName, psoHdrValue); octstr_truncate(psoHdrName, 0); /* Content-location */ octstr_append_cstr(psoHdrName, "Content-location"); psoHdrValue = http_header_value(psoHdrList, psoHdrName); octstr_format_append(p_psoHdrs, "\r\n%S;%S", psoHdrName, psoHdrValue); octstr_truncate(psoHdrName, 0); /**/ /* формируем имя файла */ psoFileName = octstr_create(p_pszWebDir); if('/' != octstr_get_char(psoFileName, octstr_len(psoFileName) - 1)) { octstr_append_char(psoFileName, '/'); } octstr_append(psoFileName, psoHdrValue); /* создаем файл */ iFile = open(octstr_get_cstr(psoFileName), O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(0 > iFile) { if(errno != EEXIST) { iRetVal = 7; goto done; } } psoMIMEOStr = mime_entity_body(p_psoMIME); octstr_base64_to_binary(psoMIMEOStr); if(octstr_len(psoMIMEOStr) != write(iFile, octstr_get_cstr(psoMIMEOStr), octstr_len(psoMIMEOStr))) { iRetVal = 8; goto done; } done: if(psoHdrName) { octstr_destroy(psoHdrName); } if(psoFileName) { octstr_destroy(psoFileName); } if(0 < iFile) { close(iFile); } return iRetVal; }
/* * This routine is used for mime_[http|octstr]_to_entity() in order to * reduce code duplication. Basically the only difference is how the headers * are parsed or passed to the resulting MIMEEntity representation. */ static MIMEEntity *mime_something_to_entity(Octstr *mime, List *headers) { MIMEEntity *e; ParseContext *context; Octstr *value, *boundary, *start; int len = 0; debug("mime.parse",0,"mime_something_to_entity"); octstr_dump(mime,0); gw_assert(mime != NULL); value = boundary = start = NULL; context = parse_context_create(mime); e = mime_entity_create(); /* parse the headers up to the body. If we have headers already passed * from our caller, then duplicate them and continue */ if (headers != NULL) { /* we have some headers to duplicate, first ensure we destroy * the list from the previous creation inside mime_entity_create() */ http_destroy_headers(e->headers); e->headers = http_header_duplicate(headers); } else { /* parse the headers out of the mime block */ if ((read_mime_headers(context, e->headers) != 0) || e->headers == NULL) { debug("mime.parse",0,"Failed to read MIME headers in Octstr block:"); octstr_dump(mime, 0); mime_entity_destroy(e); parse_context_destroy(context); return NULL; } } /* * Now check if the body is a multipart. This is indicated by an 'boundary' * parameter in the 'Content-Type' value. If yes, call ourself for the * multipart entities after parsing them. */ value = http_header_value(e->headers, octstr_imm("Content-Type")); debug("mime.parse",0,"value: %s", octstr_get_cstr(value)); boundary = http_get_header_parameter(value, octstr_imm("boundary")); debug("mime.parse",0,"boundary: %s", octstr_get_cstr(boundary)); start = get_start_param(value); /* Beware that we need *unquoted* strings to compare against in the * following parsing sections. */ if (boundary && (len = octstr_len(boundary)) > 0 && octstr_get_char(boundary, 0) == '"' && octstr_get_char(boundary, len-1) == '"') { octstr_delete(boundary, 0, 1); octstr_delete(boundary, len-2, 1); } debug("mime.parse",0, "Boundrary is %s", octstr_get_cstr(boundary)); if (boundary != NULL) { /* we have a multipart block as body, parse the boundary blocks */ Octstr *entity, *seperator, *os; /* loop by all boundary blocks we have in the body */ seperator = octstr_create("--"); octstr_append(seperator, boundary); while ((entity = parse_get_seperated_block(context, seperator)) != NULL) { MIMEEntity *m; int del2 = 0; /* we have still linefeeds at the beginning and end that we * need to remove, these are from the separator. * We check if it is LF only or CRLF! */ del2 = (octstr_get_char(entity, 0) == '\r'); if (del2) octstr_delete(entity, 0, 2); else octstr_delete(entity, 0, 1); /* we assume the same mechanism applies to beginning and end -- * seems reasonable! */ if (del2) octstr_delete(entity, octstr_len(entity) - 2, 2); else octstr_delete(entity, octstr_len(entity) - 1, 1); debug("mime.parse",0,"MIME multipart: Parsing entity:"); octstr_dump(entity, 0); /* call ourself for this MIME entity and inject to list */ if ((m = mime_octstr_to_entity(entity))) { gwlist_append(e->multiparts, m); /* check if this entity is our start entity (in terms of related) * and set our start pointer to it */ if (cid_matches(m->headers, start)) { /* set only if none has been set before */ e->start = (e->start == NULL) ? m : e->start; } } octstr_destroy(entity); } /* ok, we parsed all blocks, we expect to see now the end boundary */ octstr_append_cstr(seperator, "--"); os = parse_get_line(context); if (os != NULL && octstr_compare(os, seperator) != 0) { debug("mime.parse",0,"Failed to see end boundary, parsed line is '%s'.", octstr_get_cstr(os)); } octstr_destroy(seperator); octstr_destroy(os); } else { /* we don't have boundaries, so this is no multipart block, * pass the body to the MIME entity. */ e->body = parse_get_rest(context); } parse_context_destroy(context); octstr_destroy(value); octstr_destroy(boundary); octstr_destroy(start); return e; }