/* Parse the data stream for packets, and send out replies. */ static void parse_data(Octstr *in, Octstr *out) { int stx, etx; Octstr *packet; for (;;) { /* Look for start of packet. Delete everything up to the start * marker. (CIMD2 section 3.1 says we can ignore any data * transmitted between packets.) */ stx = octstr_search_char(in, STX, 0); if (stx < 0) octstr_delete(in, 0, octstr_len(in)); else if (stx > 0) octstr_delete(in, 0, stx); etx = octstr_search_char(in, ETX, 0); if (etx < 0) return; /* Incomplete packet; wait for more data. */ /* Copy the data between stx and etx */ packet = octstr_copy(in, 1, etx - 1); /* Then cut the packet (including stx and etx) from inbuffer */ octstr_delete(in, 0, etx + 1); parse_packet(packet, out); octstr_destroy(packet); } }
Octstr *conn_read_line(Connection *conn) { Octstr *result = NULL; long pos; lock_in(conn); /* 10 is the code for linefeed. We don't rely on \n because that * might be a different value on some (strange) systems, and * we are reading from a network connection. */ pos = octstr_search_char(conn->inbuf, 10, conn->inbufpos); if (pos < 0) { unlocked_read(conn); pos = octstr_search_char(conn->inbuf, 10, conn->inbufpos); if (pos < 0) { unlock_in(conn); return NULL; } } result = unlocked_get(conn, pos - conn->inbufpos); gw_claim_area(result); /* Skip the LF, which we left in the buffer */ conn->inbufpos++; /* If the line was terminated with CR LF, we have to remove * the CR from the result. */ if (octstr_len(result) > 0 && octstr_get_char(result, octstr_len(result) - 1) == 13) octstr_delete(result, octstr_len(result) - 1, 1); unlock_in(conn); return result; }
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; }
void set_charset(Octstr *document, Octstr *charset) { long gt = 0, enc = 0; Octstr *encoding = NULL, *text = NULL, *temp = NULL; if (octstr_len(charset) == 0) return; encoding = octstr_create(" encoding"); enc = octstr_search(document, encoding, 0); gt = octstr_search_char(document, '>', 0); if (enc < 0 || enc > gt) { gt++; text = octstr_copy(document, gt, octstr_len(document) - gt); if (charset_to_utf8(text, &temp, charset) >= 0) { octstr_delete(document, gt, octstr_len(document) - gt); octstr_append_data(document, octstr_get_cstr(temp), octstr_len(temp)); } octstr_destroy(temp); octstr_destroy(text); } octstr_destroy(encoding); }
/* Skip a beginning or ending tag in HTML, including any attributes. */ static void skip_html_tag(Octstr *html, long *pos) { long i, len; int c; /* Skip leading '<'. */ ++(*pos); /* Skip name of tag and attributes with values. */ len = octstr_len(html); while (*pos < len && (c = octstr_get_char(html, *pos)) != '>') { if (c == '"' || c == '\'') { i = octstr_search_char(html, c, *pos + 1); if (i == -1) *pos = len; else *pos = i + 1; } else ++(*pos); } /* Skip trailing '>' if it is there. */ if (octstr_get_char(html, *pos) == '>') ++(*pos); }
static void fixup_relayed_report(MmsMsg *m, MmscGrp *mmc, char *rtype, Octstr *status) { Octstr *value = mms_get_header_value(m, octstr_imm("Message-ID")); Octstr *newmsgid = NULL, *transid = NULL; /* Firstly, take care to look for the record we saved, and re-write the MessageID. */ if (value && mms_dlr_url_get(value, rtype, mmc->group_id, &newmsgid, &transid) == 0) { int x = octstr_search_char(newmsgid, ':', 0); if (x>=0) octstr_delete(newmsgid, 0, x+1); mms_replace_header_value(m, "Message-ID", octstr_get_cstr(newmsgid)); /* Add it back as original. */ mms_replace_header_value(m, "X-Mbuni-Orig-Message-ID", octstr_get_cstr(value)); #if 0 if (strcmp(rtype, "read-report") == 0 || (octstr_case_compare(status, octstr_imm("Deferred")) != 0 && octstr_case_compare(status, octstr_imm("Forwarded")) != 0)) mms_dlr_url_remove(value, rtype, mmc->group_id); /* only remove if not * interim status */ #endif } octstr_destroy(newmsgid); octstr_destroy(transid); octstr_destroy(value); }
int parse_charset(Octstr *os) { Octstr *charset = NULL; Octstr *number = NULL; int i, j, cut = 0, ret = 0; gw_assert(os != NULL); charset = octstr_duplicate(os); /* The charset might be in lower case, so... */ octstr_convert_range(charset, 0, octstr_len(charset), toupper); /* * The character set is handled in two parts to make things easier. * The cutting. */ if ((cut = octstr_search_char(charset, '_', 0)) > 0) { number = octstr_copy(charset, cut + 1, (octstr_len(charset) - (cut + 1))); octstr_truncate(charset, cut); } else if ((cut = octstr_search_char(charset, '-', 0)) > 0) { number = octstr_copy(charset, cut + 1, (octstr_len(charset) - (cut + 1))); octstr_truncate(charset, cut); } /* And table search. */ for (i = 0; character_sets[i].charset != NULL; i++) if (octstr_str_compare(charset, character_sets[i].charset) == 0) { for (j = i; octstr_str_compare(charset, character_sets[j].charset) == 0; j++) if (octstr_str_compare(number, character_sets[j].nro) == 0) { ret = character_sets[j].MIBenum; break; } break; } /* UTF-8 is the default value */ if (character_sets[i].charset == NULL) ret = character_sets[i-1].MIBenum; octstr_destroy(number); octstr_destroy(charset); return ret; }
static void check_reversible(void) { Octstr *dates; long pos, endpos, tabpos; Octstr *date, *canondate; long timeval; dates = octstr_read_file("checks/test_dates"); if (dates == NULL) return; for (pos = 0; ; pos = endpos + 1) { endpos = octstr_search_char(dates, '\n', pos); if (endpos < 0) break; tabpos = octstr_search_char(dates, '\t', pos); if (tabpos >= 0 && tabpos < endpos) { date = octstr_copy(dates, pos, tabpos - pos); canondate = octstr_copy(dates, tabpos + 1, endpos - tabpos - 1); } else { date = octstr_copy(dates, pos, endpos - pos); canondate = octstr_duplicate(date); } timeval = date_parse_http(date); if (timeval == -1) warning(0, "Could not parse date \"%s\"", octstr_get_cstr(date)); else { Octstr *newdate; newdate = date_format_http((unsigned long) timeval); if (octstr_compare(newdate, canondate) != 0) { warning(0, "Date not reversible: \"%s\" becomes \"%s\"", octstr_get_cstr(date), octstr_get_cstr(newdate)); } octstr_destroy(newdate); } octstr_destroy(date); octstr_destroy(canondate); } octstr_destroy(dates); }
static void skip_until_after_colon(Octstr *os, long *pos) { long colon = octstr_search_char(os, ':', *pos); if (colon == -1) warning(0, "SMASI: No colon after SMASI PDU name: %s", octstr_get_cstr(os)); *pos = colon + 1; }
static Octstr *decode_type(Octstr *os) { long p1, p2; Octstr *temp; if ((p2 = octstr_search_char(os, ':', 0)) == -1) return NULL; if ((p1 = octstr_search_char(os, '!', 0)) != -1 && p1 < p2) { p1++; } else { p1 = 0; } temp = octstr_copy(os, p1, p2 - p1); return temp; }
Octstr *copy_and_clean_address(Octstr *addr) { Octstr *s; int k, i; if (addr == NULL) return NULL; s = octstr_duplicate(addr); octstr_strip_blanks(s); /* Only clean up email addresses for now. */ if ((k = octstr_search_char(s, '@',0)) < 0) goto done; /* Find '<' if any, then find last one and remove everything else. */ i = octstr_search_char(s, '<',0); if (i >= 0) { int j; octstr_delete(s, 0, i+1); /* strip first part off. */ j = octstr_search_char(s, '>',0); if (j >= 0) octstr_delete(s, j, octstr_len(s)); } else { /* remove everything after the domain. */ int n = octstr_len(s); char *p = octstr_get_cstr(s); for (i = k+1; i < n; i++) if (isspace(p[i])) { /* there can't be space in domain, so this marks end of address. */ octstr_delete(s, i, n); break; } } done: if (octstr_len(s) == 0) { octstr_destroy(s); s = NULL; } return s; }
static int skip_tail(Octstr **os, int delimiter) { long delimiter_pos; if ((delimiter_pos = octstr_search_char(*os, delimiter, 0)) == -1) return 0; octstr_delete(*os, delimiter_pos, octstr_len(*os) - delimiter_pos); return 1; }
List *wsp_cap_unpack_list(Octstr *caps) { List *caps_list; long pos, capslen; caps_list = gwlist_create(); if (caps == NULL) return caps_list; capslen = octstr_len(caps); pos = 0; while (pos < capslen) { unsigned long length; int id; Octstr *name; Octstr *data; pos = octstr_extract_uintvar(caps, &length, pos); if (pos < 0 || length == 0) goto error; id = octstr_get_char(caps, pos); if (id >= 0x80) { id &= 0x7f; /* It's encoded as a short-integer */ name = NULL; data = octstr_copy(caps, pos + 1, length - 1); } else { long nullpos; id = -1; /* It's encoded as token-text */ nullpos = octstr_search_char(caps, 0, pos); if (nullpos < 0) goto error; /* check length * FIXME: If it's not allowed that data is empty then change check * to <= . */ if (length < (nullpos + 1 - pos)) goto error; name = octstr_copy(caps, pos, nullpos - pos); data = octstr_copy(caps, nullpos + 1, length - (nullpos + 1 - pos)); } gwlist_append(caps_list, wsp_cap_create(id, name, data)); pos += length; } return caps_list; error: warning(0, "WSP: Error unpacking capabilities"); return caps_list; }
Octstr *wsp_cap_pack_list(List *caps_list) { Octstr *result; Capability *cap; long i, len; result = octstr_create(""); len = gwlist_len(caps_list); for (i = 0; i < len; i++) { long datalen; cap = gwlist_get(caps_list, i); datalen = 0; if (cap->data) datalen = octstr_len(cap->data); if (datalen == 0 && cap->accept) continue; if (cap->name) { if (octstr_get_char(cap->name, 0) >= 0x80 || octstr_search_char(cap->name, 0, 0) >= 0) { error(0, "WSP: Bad capability."); wsp_cap_dump(cap); continue; } /* Add length */ octstr_append_uintvar(result, octstr_len(cap->name) + 1 + datalen); /* Add identifier */ octstr_append(result, cap->name); octstr_append_char(result, 0); } else { if (cap->id >= 0x80 || cap->id < 0) { error(0, "WSP: Bad capability."); wsp_cap_dump(cap); continue; } /* Add length */ octstr_append_uintvar(result, 1 + datalen); /* Add identifier */ octstr_append_char(result, 0x80 | cap->id); } /* Add payload, if any */ if (cap->data) { octstr_append(result, cap->data); } } return result; }
static Octstr *read_line(FILE *f, Octstr *buf) { Octstr *os; char cbuf[8*1024]; size_t n; long pos; pos = octstr_search_char(buf, '\n', 0); while (pos == -1 && (n = fread(cbuf, 1, sizeof(cbuf), f)) > 0) { octstr_append_data(buf, cbuf, n); pos = octstr_search_char(buf, '\n', 0); } if (pos == -1) { pos = octstr_len(buf); if (pos == 0) return NULL; } os = octstr_copy(buf, 0, pos); octstr_delete(buf, 0, pos + 1); return os; }
static Octstr *copy_until_coma(Octstr *os, long *pos) { long nul; Octstr *data; nul = octstr_search_char(os, ',', *pos); if (nul == -1) { warning(0, "SMASI: Parameter without value or value not properly terminated: %s", octstr_get_cstr(os)); return NULL; } data = octstr_copy(os, *pos, nul - *pos); *pos = nul + 1; return data; }
static Octstr *cgw_encode_msg(Octstr* str) { int i; char esc = 27; char e = 'e'; /* Euro char (0x80) -> ESC + e. We do this conversion as long as the message length is under 160 chars (the checking could probably be done better) */ while ((i = octstr_search_char(str, 0x80, 0)) != -1) { octstr_delete(str, i, 1); /* delete Euro char */ if (octstr_len(str) < 160) { octstr_insert_data(str, i, &esc, 1); /* replace with ESC + e */ octstr_insert_data(str, i+1, &e, 1); } else { octstr_insert_data(str, i, &e, 1); /* no room for ESC + e, just replace with an e */ } } /* Escape backslash characters */ while ((i = octstr_search_char(str, '\\', 0)) != -1) { octstr_insert(str, octstr_imm("\\"), i); } /* Remove Line Feed characters */ while ((i = octstr_search_char(str, CGW_EOL, 0)) != -1) { octstr_delete(str, i, 1); /* delete EOL char */ octstr_insert(str, octstr_imm("\\n"), i); } /* Remove Carriage return characters */ while ((i = octstr_search_char(str, 13, 0)) != -1) { octstr_delete(str, i, 1); /* delete EOL char */ octstr_insert(str, octstr_imm("\\r"), i); } return str; }
static Octstr *copy_until_assign(Octstr *os, long *pos) { long nul; Octstr *data; nul = octstr_search_char(os, '=', *pos); if (nul == -1 && (octstr_len(os) - *pos) > 1) { warning(0, "SMASI: Garbage at end of parameter list: %s", octstr_get_cstr(os)); *pos = octstr_len(os); return NULL; } data = octstr_copy(os, *pos, nul - *pos); *pos = nul + 1; return data; }
Octstr *parse_get_nul_string(ParseContext *context) { Octstr *result; long pos; gw_assert(context != NULL); pos = octstr_search_char(context->data, 0, context->pos); if (pos < 0 || pos >= context->limit) { context->error = 1; return NULL; } result = octstr_copy(context->data, context->pos, pos - context->pos); context->pos = pos + 1; return result; }
static Octstr *copy_until_nul(Octstr *os, long *pos, long max_octets) { long nul; Octstr *data; nul = octstr_search_char(os, '\0', *pos); if (nul == -1) { warning(0, "SMPP: PDU NULL terminated string has no NULL."); return NULL; } if (*pos + max_octets < nul) { error(0, "SMPP: PDU NULL terminated string longer than allowed."); return NULL; } data = (nul - *pos > 0) ? octstr_copy(os, *pos, nul - *pos) : NULL; *pos = nul + 1; return data; }
static int copy_until_nul(const char *field_name, Octstr *os, long *pos, long max_octets, Octstr **data) { long nul; *data = NULL; nul = octstr_search_char(os, '\0', *pos); if (nul == -1) { warning(0, "SMPP: PDU NULL terminated string (%s) has no NULL.", field_name); return -1; } if (*pos + max_octets < nul) { error(0, "SMPP: PDU NULL terminated string (%s) longer than allowed.", field_name); return -1; } *data = (nul - *pos > 0) ? octstr_copy(os, *pos, nul - *pos) : NULL; *pos = nul + 1; return 0; }
/* * Find the appropriate translation */ static URLTranslation *find_translation(URLTranslationList *trans, Msg *msg) { Octstr *data; int i; URLTranslation *t = NULL; List *list, *words; /* convert tolower and try to match */ data = octstr_duplicate(msg->sms.msgdata); i = 0; while((i = octstr_search_char(data, 0, i)) != -1 && i < octstr_len(data) - 1) { octstr_delete(data, i, 1); } list = get_matching_translations(trans, data); words = octstr_split_words(data); /** * List now contains all translations where the keyword of the sms * matches the pattern defined by the tranlsation's keyword. */ for (i = 0; i < gwlist_len(list); ++i) { t = gwlist_get(list, i); /* TODO check_num_args, do we really need this??? */ if (check_allowed_translation(t, msg->sms.smsc_id, msg->sms.sender, msg->sms.receiver, msg->sms.account) == 0 && check_num_args(t, words) == 0) break; t = NULL; } octstr_destroy(data); gwlist_destroy(words, octstr_destroy_item); gwlist_destroy(list, NULL); return t; }
static Octstr *get_header_value(Octstr *header) { Octstr *h = NULL; long colon = -1; if (header == NULL) { error(0, "get_header_value: NULL argument"); return NULL; } octstr_strip_blanks(header); colon = octstr_search_char(header, ':', 0); if (colon == -1) { error(0, "get_header_value: Malformed header (%s)", octstr_get_cstr (header)); return NULL; } else { h = octstr_copy(header, colon + 1, octstr_len(header)); octstr_strip_blanks(h); } debug("wap.wsp.http", 0, "get_header_value: Value (%s)", octstr_get_cstr (h)); return h; }
static Octstr *eat_string_parm(Octstr *packet, int parm, int maxlen) { long start, datastart; long tab; Octstr *result; Octstr *parmheader; parmheader = octstr_format("%c%03d:", TAB, parm); start = octstr_search(packet, parmheader, 0); if (start < 0) { octstr_destroy(parmheader); return NULL; } datastart = start + octstr_len(parmheader); tab = octstr_search_char(packet, TAB, datastart + 1); if (tab < 0) { tab = octstr_len(packet); } result = octstr_copy(packet, datastart, tab - datastart); octstr_delete(packet, start, tab - start); octstr_destroy(parmheader); return result; }
static void httpd_serve(HTTPClient *client, Octstr *ourl, List *headers, Octstr *body, List *cgivars) { Octstr *reply, *final_reply, *url; char *content_type; char *header, *footer; int status_type; int i; long pos; reply = final_reply = NULL; /* for compiler please */ url = octstr_duplicate(ourl); /* Set default reply format according to client * Accept: header */ if (http_type_accepted(headers, "text/vnd.wap.wml")) { status_type = BBSTATUS_WML; content_type = "text/vnd.wap.wml"; } else if (http_type_accepted(headers, "text/html")) { status_type = BBSTATUS_HTML; content_type = "text/html"; } else if (http_type_accepted(headers, "text/xml")) { status_type = BBSTATUS_XML; content_type = "text/xml"; } else { status_type = BBSTATUS_TEXT; content_type = "text/plain"; } /* kill '/cgi-bin' prefix */ pos = octstr_search(url, octstr_imm("/cgi-bin/"), 0); if (pos != -1) octstr_delete(url, pos, 9); else if (octstr_get_char(url, 0) == '/') octstr_delete(url, 0, 1); /* look for type and kill it */ pos = octstr_search_char(url, '.', 0); if (pos != -1) { Octstr *tmp = octstr_copy(url, pos+1, octstr_len(url) - pos - 1); octstr_delete(url, pos, octstr_len(url) - pos); if (octstr_str_compare(tmp, "txt") == 0) status_type = BBSTATUS_TEXT; else if (octstr_str_compare(tmp, "html") == 0) status_type = BBSTATUS_HTML; else if (octstr_str_compare(tmp, "xml") == 0) status_type = BBSTATUS_XML; else if (octstr_str_compare(tmp, "wml") == 0) status_type = BBSTATUS_WML; octstr_destroy(tmp); } for (i=0; httpd_commands[i].command != NULL; i++) { if (octstr_str_compare(url, httpd_commands[i].command) == 0) { reply = httpd_commands[i].function(cgivars, status_type); break; } } /* check if command found */ if (httpd_commands[i].command == NULL) { char *lb = bb_status_linebreak(status_type); reply = octstr_format("Unknown command `%S'.%sPossible commands are:%s", ourl, lb, lb); for (i=0; httpd_commands[i].command != NULL; i++) octstr_format_append(reply, "%s%s", httpd_commands[i].command, lb); } gw_assert(reply != NULL); if (status_type == BBSTATUS_HTML) { header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n" "<html>\n<title>" GW_NAME "</title>\n<body>\n<p>"; footer = "</p>\n</body></html>\n"; content_type = "text/html"; } else if (status_type == BBSTATUS_WML) { header = "<?xml version=\"1.0\"?>\n" "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" " "\"http://www.wapforum.org/DTD/wml_1.1.xml\">\n" "\n<wml>\n <card>\n <p>"; footer = " </p>\n </card>\n</wml>\n"; content_type = "text/vnd.wap.wml"; } else if (status_type == BBSTATUS_XML) { header = "<?xml version=\"1.0\"?>\n" "<gateway>\n"; footer = "</gateway>\n"; } else { header = ""; footer = ""; content_type = "text/plain"; } final_reply = octstr_create(header); octstr_append(final_reply, reply); octstr_append_cstr(final_reply, footer); /* debug("bb.http", 0, "Result: '%s'", octstr_get_cstr(final_reply)); */ http_destroy_headers(headers); headers = list_create(); http_header_add(headers, "Content-Type", content_type); http_send_reply(client, HTTP_OK, headers, final_reply); octstr_destroy(url); octstr_destroy(ourl); octstr_destroy(body); octstr_destroy(reply); octstr_destroy(final_reply); http_destroy_headers(headers); http_destroy_cgiargs(cgivars); }
int date_parse_iso (struct universaltime *ut, Octstr *os) { int n = 0; char *p, *q; /* assign defaults */ ut->month = 0; ut->day = 1; ut->hour = 0; ut->minute = 0; ut->second = 0; p = octstr_get_cstr(os); q = p + ((n = octstr_search_char(os, 'T', 0)) >= 0 ? n : octstr_len(os)); /* stop at the end of string or at the time separator */ if (sscanf(p, "%4ld%n", &ut->year, &n) < 1) return -1; p += n; if (ut->year < 70) ut->year += 2000; else if (ut->year < 100) ut->year += 1900; while (p < q && !gw_isdigit(*p)) p++; if (sscanf(p, "%2ld%n", &ut->month, &n) < 1) return 0; p += n; /* 0-based months */ if (ut->month > 0) ut->month--; while (p < q && !gw_isdigit(*p)) p++; if (sscanf(p, "%2ld%n", &ut->day, &n) < 1) return 0; p += n; if (*q == 'T') p = q+1; else return 0; while (*p && !gw_isdigit(*p)) p++; if (sscanf(p, "%2ld%n", &ut->hour, &n) < 1) return 0; p += n; while (*p && !gw_isdigit(*p)) p++; if (sscanf(p, "%2ld%n", &ut->minute, &n) < 1) return 0; p += n; while (*p && !gw_isdigit(*p)) p++; if (sscanf(p, "%2ld%n", &ut->second, &n) < 1) return 0; p += n; return 0; }
long date_parse_http(Octstr *date) { long pos; struct universaltime t; Octstr *monthstr = NULL; /* First, skip the leading day-of-week string. */ pos = octstr_search_char(date, ' ', 0); if (pos < 0 || pos == octstr_len(date) - 1) return -1; pos++; /* Skip the space */ /* Distinguish between the three acceptable formats */ if (isdigit(octstr_get_char(date, pos)) && octstr_get_char(date, pos + 2) == ' ') { if (octstr_len(date) - pos < (long)strlen("06 Nov 1994 08:49:37 GMT")) goto error; if (octstr_parse_long(&t.day, date, pos, 10) != pos + 2) goto error; monthstr = octstr_copy(date, pos + 3, 3); if (octstr_parse_long(&t.year, date, pos + 7, 10) != pos + 11) goto error; if (octstr_parse_long(&t.hour, date, pos + 12, 10) != pos + 14) goto error; if (octstr_parse_long(&t.minute, date, pos + 15, 10) != pos + 17) goto error; if (octstr_parse_long(&t.second, date, pos + 18, 10) != pos + 20) goto error; /* Take the GMT part on faith. */ } else if (isdigit(octstr_get_char(date, pos)) && octstr_get_char(date, pos + 2) == '-') { if (octstr_len(date) - pos < (long)strlen("06-Nov-94 08:49:37 GMT")) goto error; if (octstr_parse_long(&t.day, date, pos, 10) != pos + 2) goto error; monthstr = octstr_copy(date, pos + 3, 3); if (octstr_parse_long(&t.year, date, pos + 7, 10) != pos + 9) goto error; if (t.year > 60) t.year += 1900; else t.year += 2000; if (octstr_parse_long(&t.hour, date, pos + 10, 10) != pos + 12) goto error; if (octstr_parse_long(&t.minute, date, pos + 13, 10) != pos + 15) goto error; if (octstr_parse_long(&t.second, date, pos + 16, 10) != pos + 18) goto error; /* Take the GMT part on faith. */ } else { if (octstr_len(date) - pos < (long)strlen(" 6 08:49:37 1994")) goto error; monthstr = octstr_copy(date, pos, 3); if (octstr_parse_long(&t.day, date, pos + 4, 10) != pos + 6) goto error; if (octstr_parse_long(&t.hour, date, pos + 7, 10) != pos + 9) goto error; if (octstr_parse_long(&t.minute, date, pos + 10, 10) != pos + 12) goto error; if (octstr_parse_long(&t.second, date, pos + 13, 10) != pos + 15) goto error; if (octstr_parse_long(&t.year, date, pos + 16, 10) != pos + 20) goto error; } for (t.month = 0; t.month < 12; t.month++) { if (octstr_str_compare(monthstr, monthname[t.month]) == 0) break; } if (t.month == 12) goto error; octstr_destroy(monthstr); return date_convert_universal(&t); error: octstr_destroy(monthstr); return -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 void wrapper_sender(void *arg) { Msg *msg; SMSCConn *conn = arg; SmscWrapper *wrap = conn->data; /* Make sure we log into our own log-file if defined */ log_thread_to(conn->log_idx); /* send messages to SMSC until our outgoing_list is empty and * no producer anymore (we are set to shutdown) */ while(conn->status != SMSCCONN_DEAD) { if ((msg = gwlist_consume(wrap->outgoing_queue)) == NULL) break; if (octstr_search_char(msg->sms.receiver, ' ', 0) != -1) { /* * multi-send: this should be implemented in corresponding * SMSC protocol, but while we are waiting for that... */ int i; Msg *newmsg; /* split from spaces: in future, split with something more sensible, * this is dangerous... (as space is url-encoded as '+') */ List *nlist = octstr_split_words(msg->sms.receiver); debug("bb.sms", 0, "Handling multi-receiver message"); for(i=0; i < gwlist_len(nlist); i++) { newmsg = msg_duplicate(msg); octstr_destroy(newmsg->sms.receiver); newmsg->sms.receiver = gwlist_get(nlist, i); sms_send(conn, newmsg); } gwlist_destroy(nlist, NULL); msg_destroy(msg); } else sms_send(conn,msg); } /* cleanup, we are now dying */ debug("bb.sms", 0, "SMSCConn %s sender died, waiting for receiver", octstr_get_cstr(conn->name)); conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; if (conn->is_stopped) { gwlist_remove_producer(wrap->stopped); conn->is_stopped = 0; } gwthread_wakeup(wrap->receiver_thread); gwthread_join(wrap->receiver_thread); /* call 'failed' to all messages still in queue */ mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_DEAD; while((msg = gwlist_extract_first(wrap->outgoing_queue))!=NULL) { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL); } smscwrapper_destroy(wrap); conn->data = NULL; mutex_unlock(conn->flow_mutex); bb_smscconn_killed(); }
mCfg *mms_cfg_read(Octstr *file) { Octstr *sf; List *lines; int i, n; mCfg *cfg; mCfgGrp *grp = NULL; int skip = 0; gw_assert(file); if ((sf = octstr_read_file(octstr_get_cstr(file))) == NULL) { mms_error(errno, "mms_cfg", NULL, "failed to read config from `%s'", octstr_get_cstr(file)); return NULL; } cfg = gw_malloc(sizeof *cfg); cfg->file = octstr_duplicate(file); cfg->grps = dict_create(7, NULL); cfg->xcfg = NULL; cfg->cfg_funcs = NULL; lines = octstr_split(sf, octstr_imm("\n")); for (i = 0, n = gwlist_len(lines); i < n; i++) { Octstr *current = gwlist_get(lines,i); int pos; octstr_strip_blanks(current); if (octstr_len(current) == 0) { /* end of group. */ grp = NULL; skip = 0; continue; } else if (skip || octstr_get_char(current, 0) == '#') continue; if ((pos = octstr_search_char(current, '=',0)) > 0) { /* a field name. first see if start of grp */ Octstr *field = octstr_copy(current,0,pos); Octstr *value = octstr_copy(current,pos+1,octstr_len(current)); octstr_strip_blanks(field); fixup_value(value, i+1); #if 0 mms_info(0, "mms_cfg", NULL, "field/value: [%s - %s]", octstr_get_cstr(field), octstr_get_cstr(value)); #endif if (octstr_str_case_compare(field, "group") == 0) if (grp == NULL) { /* grp name. */ int ismulti = is_multigroup(value); if (ismulti < 0) { mms_info(0, "mms_cfg", NULL, "Skipping unknown group `%s' at line %d of conf file", octstr_get_cstr(value), i+1); skip = 1; } else { grp = gw_malloc(sizeof *grp); grp->name = octstr_duplicate(value); grp->fields = dict_create(23, (void (*)(void *))octstr_destroy); if (ismulti) { List *l = dict_get(cfg->grps, value); if (l == NULL) { l = gwlist_create(); dict_put(cfg->grps, value, l); } gwlist_append(l, grp); } else if (dict_put_once(cfg->grps, value, grp) == 0) panic(0, "Group `%s' [at line %d] cannot appear more " "than once in config!", octstr_get_cstr(value), i+1); } } else panic(0,"`group' is an illegal field name " "within a group at line %d in config file!", i+1); else if (grp) /* an ordinary field name. */ check_and_add_field(grp, field, value,i+1); else panic(0, "A group must begin with a `group = group_name' " "clause [at line %d in config file]", i+1); octstr_destroy(field); octstr_destroy(value); } else panic(0, "mal-formed entry in conf file at line %d!", i+1); } gwlist_destroy(lines, (gwlist_item_destructor_t *)octstr_destroy); octstr_destroy(sf); /* Now check if config-source is set, use that. */ if ((grp = mms_cfg_get_single(cfg, octstr_imm("config-source"))) != NULL) { Octstr *init = mms_cfg_get(cfg, grp, octstr_imm("config-library-init-param")); cfg->cfg_funcs = _mms_load_module(cfg, grp, "config-library", "cfg_funcs", NULL); if (cfg->cfg_funcs == NULL || cfg->cfg_funcs->read == NULL || (cfg->xcfg = cfg->cfg_funcs->read(init)) == NULL) { mms_error(0, "mms_cfg", NULL, "Failed to load cfg reader library from conf!"); mms_cfg_destroy(cfg); cfg = NULL; } octstr_destroy(init); } return cfg; }