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_octets(ParseContext *context, long length) { Octstr *result; gw_assert(context != NULL); if (context->pos + length > context->limit) { context->error = 1; return NULL; } result = octstr_copy(context->data, context->pos, length); context->pos += length; return result; }
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 *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; }
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 first packet in "in", delete it from "in", and return it as * a struct. Return NULL if "in" contains no packet. Always delete * leading non-packet data from "in". */ static struct packet *packet_extract(Octstr *in, SMSCConn *conn) { Octstr *packet; int size, i; static char s[4][4] = { { 0x01, 0x0b, 0x00, 0x00 }, { 0x01, 0x00, 0x00, 0x00 }, { 0x00, 0x04, 0x00, 0x00 }, { 0x00, 0x09, 0x00, 0x00 } }; /* msgtype, oper, 0, 0 */ char known_bytes[4]; if (octstr_len(in) < 10) return NULL; octstr_get_many_chars(known_bytes, in, 4, 4); /* Find s, and delete everything up to it. */ /* If packet starts with one of s, it should be good packet */ for (i = 0; i < 4; i++) { if (memcmp(s[i], known_bytes, 4) == 0) break; } if (i >= 4) { error(0, "OISD[%s]: wrong packet", octstr_get_cstr(conn->id)); octstr_dump(in, 0); return NULL; } /* Find end of packet */ size = (octstr_get_char(in, 9) << 8) | octstr_get_char(in, 8); if (size + 10 > octstr_len(in)) return NULL; packet = octstr_copy(in, 0, size + 10); octstr_delete(in, 0, size + 10); return packet_parse(packet); }
static void split_headers(Octstr *headers, List **split) { long start; long pos; *split = gwlist_create(); start = 0; for (pos = 0; pos < octstr_len(headers); pos++) { if (octstr_get_char(headers, pos) == '\n') { Octstr *line; if (pos == start) { /* Skip empty lines */ start = pos + 1; continue; } line = octstr_copy(headers, start, pos - start); start = pos + 1; gwlist_append(*split, line); } } }
static long pass_field_name(Octstr **body_part, Octstr **field_part, long pos) { int c; long start; Octstr *name = NULL; start = pos; while (((c = octstr_get_char(*body_part, pos)) != ':') && pos < octstr_len(*body_part)) { ++pos; } if (pos == octstr_len(*body_part)) { return -1; } name = octstr_copy(*body_part, start, pos - start); octstr_append(*field_part, name); octstr_destroy(name); return pos; }
static long pass_field_value(Octstr **body_part, Octstr **header, long pos) { int c; long start; Octstr *field = NULL; start = pos; while (!is_cr(c = octstr_get_char(*body_part, pos)) && pos < octstr_len(*body_part)) { ++pos; } if (pos == octstr_len(*body_part)) { return -1; } field = octstr_copy(*body_part, start, pos - start); octstr_append(*header, field); octstr_destroy(field); return pos; }
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 *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 *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; }
/* * Trans being NULL means that we are servicing ppg (doing dlr, but this does not * concern us here). */ Octstr *urltrans_get_pattern(URLTranslation *t, Msg *request) { Octstr *enc; int nextarg, j; struct tm tm; int num_words; List *word_list; Octstr *result, *pattern; long pattern_len; long pos; int c; long i; Octstr *temp; Octstr *url, *reply; /* For and If delivery report */ url = reply = NULL; if (request->sms.sms_type != report_mo && t->type == TRANSTYPE_SENDSMS) return octstr_create(""); if (request->sms.msgdata) { word_list = octstr_split_words(request->sms.msgdata); num_words = list_len(word_list); } else { word_list = list_create(); num_words = 0; } result = octstr_create(""); /* check if this is a delivery report message or not */ if (request->sms.sms_type != report_mo) { pattern = t->pattern; } else { /* this is a DLR message */ reply = octstr_duplicate(request->sms.msgdata); url = octstr_duplicate(request->sms.dlr_url); pattern = url; if (octstr_len(pattern) == 0) { if (t && octstr_len(t->dlr_url)) { pattern = t->dlr_url; } else { list_destroy(word_list, octstr_destroy_item); return octstr_create(""); } } } pattern_len = octstr_len(pattern); nextarg = 1; pos = 0; for (;;) { while (pos < pattern_len) { c = octstr_get_char(pattern, pos); if (c == '%' && pos + 1 < pattern_len) break; octstr_append_char(result, c); ++pos; } if (pos == pattern_len) break; switch (octstr_get_char(pattern, pos + 1)) { case 'k': if (num_words <= 0) break; enc = octstr_duplicate(list_get(word_list, 0)); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 's': if (nextarg >= num_words) break; enc = octstr_duplicate(list_get(word_list, nextarg)); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); ++nextarg; break; case 'S': if (nextarg >= num_words) break; temp = list_get(word_list, nextarg); for (i = 0; i < octstr_len(temp); ++i) { if (octstr_get_char(temp, i) == '*') octstr_append_char(result, '~'); else octstr_append_char(result, octstr_get_char(temp, i)); } ++nextarg; break; case 'r': for (j = nextarg; j < num_words; ++j) { enc = octstr_duplicate(list_get(word_list, j)); octstr_url_encode(enc); if (j != nextarg) octstr_append_char(result, '+'); octstr_append(result, enc); octstr_destroy(enc); } break; /* NOTE: the sender and receiver is already switched in * message, so that's why we must use 'sender' when * we want original receiver and vice versa */ case 'P': enc = octstr_duplicate(request->sms.sender); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'p': enc = octstr_duplicate(request->sms.receiver); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'Q': if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) { enc = octstr_copy(request->sms.sender, 2, octstr_len(request->sms.sender)); octstr_url_encode(enc); octstr_format_append(result, "%%2B%S", enc); octstr_destroy(enc); } else { enc = octstr_duplicate(request->sms.sender); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'q': if (strncmp(octstr_get_cstr(request->sms.receiver),"00",2)==0) { enc = octstr_copy(request->sms.receiver, 2, octstr_len(request->sms.receiver)); octstr_url_encode(enc); octstr_format_append(result, "%%2B%S", enc); octstr_destroy(enc); } else { enc = octstr_duplicate(request->sms.receiver); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'a': for (j = 0; j < num_words; ++j) { enc = octstr_duplicate(list_get(word_list, j)); octstr_url_encode(enc); if (j > 0) octstr_append_char(result, '+'); octstr_append(result, enc); octstr_destroy(enc); } break; case 'b': enc = octstr_duplicate(request->sms.msgdata); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 't': tm = gw_gmtime(request->sms.time); octstr_format_append(result, "%04d-%02d-%02d+%02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); break; case 'T': if (request->sms.time == MSG_PARAM_UNDEFINED) break; octstr_format_append(result, "%ld", request->sms.time); break; case 'i': if (request->sms.smsc_id == NULL) break; enc = octstr_duplicate(request->sms.smsc_id); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'I': if (!uuid_is_null(request->sms.id)) { char id[UUID_STR_LEN + 1]; uuid_unparse(request->sms.id, id); octstr_append_cstr(result, id); } break; case 'n': if (request->sms.service == NULL) break; enc = octstr_duplicate(request->sms.service); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'd': enc = octstr_create(""); octstr_append_decimal(enc, request->sms.dlr_mask); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'A': if (reply) { enc = octstr_duplicate(reply); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'c': octstr_append_decimal(result, request->sms.coding); break; case 'C': if(octstr_len(request->sms.charset)) { octstr_append(result, request->sms.charset); } else { switch (request->sms.coding) { case DC_UNDEF: case DC_7BIT: octstr_append(result, octstr_imm("ISO-8859-1")); break; case DC_8BIT: octstr_append(result, octstr_imm("8-BIT")); break; case DC_UCS2: octstr_append(result, octstr_imm("UTF16-BE")); break; } } break; case 'u': if(octstr_len(request->sms.udhdata)) { enc = octstr_duplicate(request->sms.udhdata); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'B': /* billing identifier/information */ if (octstr_len(request->sms.binfo)) { enc = octstr_duplicate(request->sms.binfo); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'o': /* account information (may be operator id for aggregators */ if (octstr_len(request->sms.account)) { enc = octstr_duplicate(request->sms.account); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; /* XXX sms.parameters not present in here: * * pid - will we receive this ? * * mwi,mclass - will we receive these bits from smsc ? * * alt-dcs - shouldn't be required unless we want to inform * which alt-dcs external server should use back * * compress - if we use compression, probably kannel would * decompress and reset this to 0. not required * * validity, deferred, rpi - we don't receive these from smsc * * username, password, dlr-url, account - nonsense to send */ case '%': octstr_format_append(result, "%%"); break; default: octstr_format_append(result, "%%%c", octstr_get_char(pattern, pos + 1)); break; } pos += 2; } /* * this SHOULD be done in smsbox, not here, but well, * much easier to do here */ if (t && (t->type == TRANSTYPE_POST_URL || t->type == TRANSTYPE_POST_XML) && t->strip_keyword) strip_keyword(request); octstr_destroy(url); octstr_destroy(reply); list_destroy(word_list, octstr_destroy_item); 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); }
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; }
Octstr *urltrans_fill_escape_codes(Octstr *pattern, Msg *request) { Octstr *enc; Octstr *meta_group, *meta_param; int nextarg, j; struct tm tm; int num_words; List *word_list; Octstr *result; long pattern_len; long pos; int c; long i, k; Octstr *temp; result = octstr_create(""); if (request->sms.msgdata) { word_list = octstr_split_words(request->sms.msgdata); num_words = gwlist_len(word_list); } else { word_list = gwlist_create(); num_words = 0; } pattern_len = octstr_len(pattern); nextarg = 1; pos = 0; for (;;) { while (pos < pattern_len) { c = octstr_get_char(pattern, pos); if (c == '%' && pos + 1 < pattern_len) break; octstr_append_char(result, c); ++pos; } if (pos == pattern_len) break; switch (octstr_get_char(pattern, pos + 1)) { case 'a': for (j = 0; j < num_words; ++j) { enc = octstr_duplicate(gwlist_get(word_list, j)); octstr_url_encode(enc); if (j > 0) octstr_append_char(result, '+'); octstr_append(result, enc); octstr_destroy(enc); } break; case 'A': if (request->sms.msgdata) { enc = octstr_duplicate(request->sms.msgdata); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'b': enc = octstr_duplicate(request->sms.msgdata); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'B': /* billing identifier/information */ if (octstr_len(request->sms.binfo)) { enc = octstr_duplicate(request->sms.binfo); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'c': octstr_append_decimal(result, request->sms.coding); break; case 'C': if (octstr_len(request->sms.charset)) { octstr_append(result, request->sms.charset); } else { switch (request->sms.coding) { case DC_UNDEF: case DC_7BIT: octstr_append(result, octstr_imm("UTF-8")); break; case DC_8BIT: octstr_append(result, octstr_imm("8-BIT")); break; case DC_UCS2: octstr_append(result, octstr_imm("UTF-16BE")); break; } } break; case 'd': enc = octstr_create(""); octstr_append_decimal(enc, request->sms.dlr_mask); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'D': /* meta_data */ if (octstr_len(request->sms.meta_data)) { enc = octstr_duplicate(request->sms.meta_data); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'f': /* smsc number*/ if (octstr_len(request->sms.smsc_number)) { enc = octstr_duplicate(request->sms.smsc_number); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'F': if (request->sms.foreign_id == NULL) break; enc = octstr_duplicate(request->sms.foreign_id); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'i': if (request->sms.smsc_id == NULL) break; enc = octstr_duplicate(request->sms.smsc_id); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'I': if (!uuid_is_null(request->sms.id)) { char id[UUID_STR_LEN + 1]; uuid_unparse(request->sms.id, id); octstr_append_cstr(result, id); } break; case 'k': if (num_words <= 0) break; enc = octstr_duplicate(gwlist_get(word_list, 0)); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'm': /* mclass - message class */ enc = octstr_create(""); octstr_append_decimal(enc, request->sms.mclass); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'M': /* mwi - message waiting indicator */ enc = octstr_create(""); octstr_append_decimal(enc, request->sms.mwi); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'n': if (request->sms.service == NULL) break; enc = octstr_duplicate(request->sms.service); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'o': /* account information (may be operator id for aggregators */ if (octstr_len(request->sms.account)) { enc = octstr_duplicate(request->sms.account); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'O': /* DCS */ { int dcs; dcs = fields_to_dcs(request, request->sms.alt_dcs); octstr_format_append(result, "%02d", dcs); break; } /* NOTE: the sender and receiver is already switched in * message, so that's why we must use 'sender' when * we want original receiver and vice versa */ case 'P': enc = octstr_duplicate(request->sms.sender); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'p': enc = octstr_duplicate(request->sms.receiver); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); break; case 'q': if (strncmp(octstr_get_cstr(request->sms.receiver),"00",2)==0) { enc = octstr_copy(request->sms.receiver, 2, octstr_len(request->sms.receiver)); octstr_url_encode(enc); octstr_format_append(result, "%%2B%S", enc); octstr_destroy(enc); } else { enc = octstr_duplicate(request->sms.receiver); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'Q': if (strncmp(octstr_get_cstr(request->sms.sender), "00", 2) == 0) { enc = octstr_copy(request->sms.sender, 2, octstr_len(request->sms.sender)); octstr_url_encode(enc); octstr_format_append(result, "%%2B%S", enc); octstr_destroy(enc); } else { enc = octstr_duplicate(request->sms.sender); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'r': for (j = nextarg; j < num_words; ++j) { enc = octstr_duplicate(gwlist_get(word_list, j)); octstr_url_encode(enc); if (j != nextarg) octstr_append_char(result, '+'); octstr_append(result, enc); octstr_destroy(enc); } break; case 'R': /* dlr_url */ if (octstr_len(request->sms.dlr_url)) { enc = octstr_duplicate(request->sms.dlr_url); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 's': if (nextarg >= num_words) break; enc = octstr_duplicate(gwlist_get(word_list, nextarg)); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); ++nextarg; break; case 'S': if (nextarg >= num_words) break; temp = gwlist_get(word_list, nextarg); for (i = 0; i < octstr_len(temp); ++i) { if (octstr_get_char(temp, i) == '*') octstr_append_char(result, '~'); else octstr_append_char(result, octstr_get_char(temp, i)); } ++nextarg; break; case 't': tm = gw_gmtime(request->sms.time); octstr_format_append(result, "%04d-%02d-%02d+%02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); break; case 'T': if (request->sms.time == MSG_PARAM_UNDEFINED) break; octstr_format_append(result, "%ld", request->sms.time); break; case 'u': if(octstr_len(request->sms.udhdata)) { enc = octstr_duplicate(request->sms.udhdata); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } break; case 'v': if (request->sms.validity != MSG_PARAM_UNDEFINED) { octstr_format_append(result, "%ld", (request->sms.validity - time(NULL)) / 60); } break; case 'V': if (request->sms.deferred != MSG_PARAM_UNDEFINED) { octstr_format_append(result, "%ld", (request->sms.deferred - time(NULL)) / 60); } break; /* * This allows to pass meta-data individual parameters into urls. * The syntax is as follows: %#group#parameter# * For example: %#smpp#my_param# would be replaced with the value * 'my_param' from the group 'smpp' coming inside the meta_data field. */ case '#': /* ASCII 0x23 == '#' */ k = octstr_search_char(pattern, 0x23, pos + 2); if (k >= 0) { pos += 2; meta_group = octstr_copy(pattern, pos, (k-pos)); pos = k + 1; k = octstr_search_char(pattern, 0x23, pos); if (k >= 0) { meta_param = octstr_copy(pattern, pos, (k-pos)); pos = k - 1; if (request->sms.meta_data != NULL) { enc = meta_data_get_value(request->sms.meta_data, octstr_get_cstr(meta_group), meta_param); octstr_url_encode(enc); octstr_append(result, enc); octstr_destroy(enc); } octstr_destroy(meta_param); } else { pos++; } octstr_destroy(meta_group); } break; /* XXX sms.parameters not present in here: * * pid - will we receive this ? * * alt-dcs - shouldn't be required unless we want to inform * which alt-dcs external server should use back * * compress - if we use compression, probably kannel would * decompress and reset this to 0. not required * * rpi - we don't receive these from smsc * * username, password, dlr-url, account - nonsense to send */ case '%': octstr_format_append(result, "%%"); break; default: octstr_format_append(result, "%%%c", octstr_get_char(pattern, pos + 1)); break; } pos += 2; } gwlist_destroy(word_list, octstr_destroy_item); return result; }
/* * Split os2 from os1, boundary being boundary_pos. */ static void octstr_split_by_pos(Octstr **os1, Octstr **os2, long boundary_pos) { *os2 = octstr_copy(*os1, 0, boundary_pos); octstr_delete(*os1, 0, boundary_pos); }
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; }
int cfg_read(Cfg *cfg) { CfgLoc *loc; CfgLoc *loc_inc; List *lines; List *expand; List *stack; Octstr *name; Octstr *value; Octstr *filename; CfgGroup *grp; long equals; long lineno; long error_lineno; loc = loc_inc = NULL; /* * expand initial main config file and add it to the recursion * stack to protect against cycling */ if ((lines = expand_file(cfg->filename, 1)) == NULL) { panic(0, "Failed to load main configuration file `%s'. Aborting!", octstr_get_cstr(cfg->filename)); } stack = gwlist_create(); gwlist_insert(stack, 0, octstr_duplicate(cfg->filename)); grp = NULL; lineno = 0; error_lineno = 0; while (error_lineno == 0 && (loc = gwlist_extract_first(lines)) != NULL) { octstr_strip_blanks(loc->line); if (octstr_len(loc->line) == 0) { if (grp != NULL && add_group(cfg, grp) == -1) { error_lineno = loc->line_no; destroy_group(grp); } grp = NULL; } else if (octstr_get_char(loc->line, 0) != '#') { equals = octstr_search_char(loc->line, '=', 0); if (equals == -1) { error(0, "An equals sign ('=') is missing on line %ld of file %s.", loc->line_no, octstr_get_cstr(loc->filename)); error_lineno = loc->line_no; } else /* * check for special config directives, like include or conditional * directives here */ if (octstr_search(loc->line, octstr_imm("include"), 0) != -1) { filename = octstr_copy(loc->line, equals + 1, octstr_len(loc->line)); parse_value(filename); /* check if we are cycling */ if (gwlist_search(stack, filename, octstr_item_match) != NULL) { panic(0, "Recursive include for config file `%s' detected " "(on line %ld of file %s).", octstr_get_cstr(filename), loc->line_no, octstr_get_cstr(loc->filename)); } else { List *files = gwlist_create(); Octstr *file; struct stat filestat; /* check if included file is a directory */ if (lstat(octstr_get_cstr(filename), &filestat) != 0) { error(errno, "lstat failed: couldn't stat `%s'", octstr_get_cstr(filename)); panic(0, "Failed to include `%s' " "(on line %ld of file %s). Aborting!", octstr_get_cstr(filename), loc->line_no, octstr_get_cstr(loc->filename)); } /* * is a directory, create a list with files of * this directory and load all as part of the * whole configuration. */ if (S_ISDIR(filestat.st_mode)) { DIR *dh; struct dirent *diritem; debug("gwlib.cfg", 0, "Loading include dir `%s' " "(on line %ld of file %s).", octstr_get_cstr(filename), loc->line_no, octstr_get_cstr(loc->filename)); dh = opendir(octstr_get_cstr(filename)); while ((diritem = readdir(dh))) { Octstr *fileitem; fileitem = octstr_duplicate(filename); octstr_append_cstr(fileitem, "/"); octstr_append_cstr(fileitem, diritem->d_name); lstat(octstr_get_cstr(fileitem), &filestat); if (!S_ISDIR(filestat.st_mode)) { gwlist_insert(files, 0, fileitem); } else { octstr_destroy(fileitem); } } closedir(dh); } /* is a file, create a list with it */ else { gwlist_insert(files, 0, octstr_duplicate(filename)); } /* include files */ while ((file = gwlist_extract_first(files)) != NULL) { gwlist_insert(stack, 0, octstr_duplicate(file)); debug("gwlib.cfg", 0, "Loading include file `%s' (on line %ld of file %s).", octstr_get_cstr(file), loc->line_no, octstr_get_cstr(loc->filename)); /* * expand the given include file and add it to the current * processed main while loop */ if ((expand = expand_file(file, 0)) != NULL) { while ((loc_inc = gwlist_extract_first(expand)) != NULL) gwlist_insert(lines, 0, loc_inc); } else { panic(0, "Failed to load whole configuration. Aborting!"); } gwlist_destroy(expand, NULL); cfgloc_destroy(loc_inc); octstr_destroy(file); } gwlist_destroy(files, octstr_destroy_item); } octstr_destroy(filename); } /* * this is a "normal" line, so process it accodingly */ else { name = octstr_copy(loc->line, 0, equals); octstr_strip_blanks(name); value = octstr_copy(loc->line, equals + 1, octstr_len(loc->line)); parse_value(value); if (grp == NULL) grp = create_group(); if (grp->configfile != NULL) { octstr_destroy(grp->configfile); grp->configfile = NULL; } grp->configfile = octstr_duplicate(cfg->filename); cfg_set(grp, name, value); octstr_destroy(name); octstr_destroy(value); } } cfgloc_destroy(loc); } if (grp != NULL && add_group(cfg, grp) == -1) { error_lineno = 1; destroy_group(grp); } gwlist_destroy(lines, NULL); gwlist_destroy(stack, octstr_destroy_item); if (error_lineno != 0) { error(0, "Error found on line %ld of file `%s'.", error_lineno, octstr_get_cstr(cfg->filename)); return -1; } return 0; }
static int sendNotify(MmsEnvelope *e) { Octstr *to; MmsMsg *msg, *smsg = NULL; MmsEnvelopeTo *xto = gwlist_get(e->to, 0); Octstr *err = NULL; time_t tnow = time(NULL); int j, k, len; Octstr *phonenum = NULL, *rcpt_ip = NULL, *msgId, *from, *fromproxy; int mtype, msize; int res = MMS_SEND_OK, dlr; time_t expiryt; char *prov_notify_event = NULL; char *rtype = NULL; if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */ e->sendt = e->expiryt + 3600*24*30*12; info(0, "MM1: Message [ID: %s] fetched/touched at least once. Skipping", e->xqfname); return settings->qfs->mms_queue_update(e); } if (!xto) { error(0, "mobilesender: Queue entry %s with no recipients!", e->xqfname); return 0; } msg = settings->qfs->mms_queue_getdata(e); to = octstr_duplicate(xto->rcpt); expiryt = e->expiryt; msgId = e->msgId ? octstr_duplicate(e->msgId) : NULL; from = octstr_duplicate(e->from); fromproxy = e->fromproxy ? octstr_duplicate(e->fromproxy) : NULL; msize = e->msize; dlr = e->dlr; if (e->expiryt != 0 && /* Handle message expiry. */ e->expiryt < tnow) { err = octstr_format("MMSC error: Message expired while sending to %S!", to); res = MMS_SEND_ERROR_FATAL; prov_notify_event = "failedfetch"; rtype = "Expired"; goto done; } else if (e->attempts >= settings->maxsendattempts) { err = octstr_format("MMSC error: Failed to deliver to %S after %ld attempts!", to, e->attempts); res = MMS_SEND_ERROR_FATAL; prov_notify_event = "failedfetch"; rtype = "Expired"; goto done; } j = octstr_case_search(to, octstr_imm("/TYPE=PLMN"), 0); k = octstr_case_search(to, octstr_imm("/TYPE=IPv"), 0); len = octstr_len(to); if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) { /* A proper number. */ phonenum = octstr_copy(to, 0, j); #if 0 normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum); #else mms_normalize_phonenum(&phonenum, octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes); #endif } else if (k > 0 && k + sizeof "/TYPE=IPv" == len) rcpt_ip = octstr_copy(to, 0, k); else { /* We only handle phone numbers here. */ err = octstr_format("Unexpected recipient %s in MT queue!", octstr_get_cstr(to)); res = MMS_SEND_ERROR_FATAL; goto done; } mtype = mms_messagetype(msg); /* For phone, getting here means the message can be delivered. So: * - Check whether the recipient is provisioned, if not, wait (script called will queue creation req) * - If the recipient can't take MMS, then send SMS. */ /* We handle two types of requests: send and delivery/read notifications. * other types of messages cannot possibly be in this queue! */ if (mtype == MMS_MSGTYPE_SEND_REQ || mtype == MMS_MSGTYPE_RETRIEVE_CONF) { Octstr *url, *transid; if (phonenum) { int send_ind = mms_ind_send(settings->prov_getstatus, phonenum); if (send_ind < 0 && settings->notify_unprovisioned) send_ind = 0; if (send_ind < 0) { /* That is, recipient is not (yet) provisioned. */ res = MMS_SEND_ERROR_TRANSIENT; err = octstr_format("%S is not provisioned for MMS reception, delivery deferred!", phonenum); /* Do not increase delivery attempts counter. */ e->lasttry = tnow; e->sendt = e->lasttry + settings->send_back_off * (1 + e->attempts); if (settings->qfs->mms_queue_update(e) == 1) e = NULL; /* Queue entry gone. */ else settings->qfs->mms_queue_free_env(e); goto done; } else if (send_ind == 0) { /* provisioned but does not support */ Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt), from); if (settings->notify_unprovisioned && s && octstr_len(s) > 0) { /* Only send if the string was set. */ List *pheaders; Octstr *sto = octstr_duplicate(phonenum); octstr_url_encode(s); octstr_url_encode(sto); url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, sto); pheaders = http_create_empty_headers(); http_header_add(pheaders, "Connection", "close"); http_header_add(pheaders, "User-Agent", MM_NAME "/" VERSION); http_start_request(httpcaller, HTTP_METHOD_GET, url, pheaders, NULL, 0, &edummy, NULL); http_destroy_headers(pheaders); octstr_destroy(url); octstr_destroy(sto); } else if (s) octstr_destroy(s); res = MMS_SEND_OK; err = octstr_imm("No MMS Ind support, sent SMS instead"); xto->process = 0; /* No more processing. */ if (settings->qfs->mms_queue_update(e) == 1) e = NULL; else settings->qfs->mms_queue_free_env(e); goto done; } } /* To get here means we can send Ind. */ url = mms_makefetchurl(e->xqfname, e->token, MMS_LOC_MQUEUE, phonenum ? phonenum : to, settings); info(0, "Preparing to notify client to fetch message at URL: %s", octstr_get_cstr(url)); transid = mms_maketransid(e->xqfname, settings->host_alias); smsg = mms_notification(msg, e->msize, url, transid, e->expiryt ? e->expiryt : tnow + settings->default_msgexpiry, settings->optimize_notification_size); octstr_destroy(transid); octstr_destroy(url); } else if (mtype == MMS_MSGTYPE_DELIVERY_IND || mtype == MMS_MSGTYPE_READ_ORIG_IND) smsg = msg; else { error(0, "Unexpected message type %s for %s found in MT queue!", mms_message_type_to_cstr(mtype), octstr_get_cstr(to)); res = MMS_SEND_ERROR_FATAL; goto done; } if (smsg) start_push(phonenum ? phonenum : rcpt_ip, phonenum ? 1 : 0, e, smsg); /* Send the message. * Don't touch 'e' after this point! * It may be freed by receive thread. */ if (smsg != msg && smsg) mms_destroy(smsg); done: if (err != NULL && res != MMS_SEND_ERROR_TRANSIENT) { /* If there was a report request and this is a legit error * queue it. */ if (dlr) { MmsMsg *m = mms_deliveryreport(msgId, to, tnow, rtype ? octstr_imm(rtype) : octstr_imm("Indeterminate")); List *l = gwlist_create(); Octstr *res; gwlist_append(l, from); /* Add to queue, switch via proxy to be from proxy. */ res = settings->qfs->mms_queue_add(to ? to : settings->system_user, l, err, NULL, fromproxy, tnow, tnow+settings->default_msgexpiry, m, NULL, NULL, NULL, NULL, NULL, NULL, 0, octstr_get_cstr(settings->mm1_queuedir), "MM2", settings->host_alias); gwlist_destroy(l, NULL); mms_destroy(m); octstr_destroy(res); } } /* Write to log */ info(0, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s", SEND_ERROR_STR(res), octstr_get_cstr(from), octstr_get_cstr(to), msize, err ? octstr_get_cstr(err) : ""); if (res == MMS_SEND_ERROR_FATAL) { xto->process = 0; /* No more attempts to deliver, delete this. */ if (settings->qfs->mms_queue_update(e) == 1) e = NULL; /* Queue entry gone. */ else settings->qfs->mms_queue_free_env(e); } /* Else queue will be updated/freed elsewhere. */ if (prov_notify_event) notify_prov_server(octstr_get_cstr(settings->prov_notify), to ? octstr_get_cstr(to) : "unknown", prov_notify_event, rtype ? rtype : "", e ? e->msgId : NULL, NULL, NULL); if (msg) mms_destroy(msg); octstr_destroy(phonenum); octstr_destroy(rcpt_ip); octstr_destroy(to); octstr_destroy(msgId); octstr_destroy(fromproxy); octstr_destroy(from); octstr_destroy(err); 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 msg_to_bb(SMSCConn *conn, Octstr *line) { long p, p2; Msg *msg; Octstr *type = NULL; /* might be destroyed after error before created */ msg = msg_create(sms); p = octstr_search_char(line, ' ', 0); if (p == -1) goto error; msg->sms.sender = octstr_copy(line, 0, p); p2 = octstr_search_char(line, ' ', p + 1); if (p2 == -1) goto error; msg->sms.receiver = octstr_copy(line, p + 1, p2 - p - 1); p = octstr_search_char(line, ' ', p2 + 1); if (p == -1) goto error; type = octstr_copy(line, p2 + 1, p - p2 - 1); if (!octstr_compare(type, octstr_imm("text"))) { msg->sms.msgdata = octstr_copy(line, p + 1, LONG_MAX); msg->sms.coding = DC_7BIT; } else if (!octstr_compare(type, octstr_imm("data"))) { msg->sms.msgdata = octstr_copy(line, p + 1, LONG_MAX); msg->sms.coding = DC_8BIT; if (octstr_url_decode(msg->sms.msgdata) == -1) warning(0, "smsc_fake: urlcoded data from client looks malformed"); } else if (!octstr_compare(type, octstr_imm("route"))) { p2 = octstr_search_char(line, ' ', p + 1); if (p2 == -1) goto error; msg->sms.boxc_id = octstr_copy(line, p + 1, p2 - p - 1); msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX); } else if (!octstr_compare(type, octstr_imm("udh"))) { p2 = octstr_search_char(line, ' ', p + 1); if (p2 == -1) goto error; msg->sms.udhdata = octstr_copy(line, p + 1, p2 - p - 1); msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX); if (msg->sms.coding == DC_UNDEF) msg->sms.coding = DC_8BIT; if (octstr_url_decode(msg->sms.msgdata) == -1 || octstr_url_decode(msg->sms.udhdata) == -1) warning(0, "smsc_fake: urlcoded data from client looks malformed"); } else if (!octstr_compare(type, octstr_imm("dlr-mask"))) { Octstr *tmp; p2 = octstr_search_char(line, ' ', p + 1); if (p2 == -1) goto error; tmp = octstr_copy(line, p + 1, p2 - p - 1); msg->sms.dlr_mask = atoi(octstr_get_cstr(tmp)); octstr_destroy(tmp); msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX); } else goto error; octstr_destroy(line); octstr_destroy(type); time(&msg->sms.time); msg->sms.smsc_id = octstr_duplicate(conn->id); debug("bb.sms", 0, "smsc_fake: new message received"); /* msg_dump(msg, 0); */ bb_smscconn_receive(conn, msg); return; error: warning(0, "smsc_fake: invalid message syntax from client, ignored"); msg_destroy(msg); octstr_destroy(line); octstr_destroy(type); return; }
struct cgwop *cgw_read_op(PrivData *privdata, SMSCConn *conn, Connection *server, time_t timeout) { Octstr *line, *name, *value; int finished = 0; int c = 0; struct cgwop *cgwop = NULL; int op = CGW_OP_NOP; if ((line = conn_read_line(server)) == NULL) return NULL; /* don't block */ do { while (line == NULL) line = conn_read_line(server); /* wait for more data */ c = octstr_search_char(line, ':', 0); if (c != -1) { name = octstr_copy(line, 0, c); value = octstr_copy(line, c + 1, octstr_len(line) - (c + 1)); if (octstr_compare(name, octstr_imm("hello")) == 0) { /* A connection is started by CGW by sending a * "hello: Provider Server..." line. */ cgwop = cgwop_create(CGW_OP_HELLO, 0); cgwop_add(cgwop, octstr_imm("hello"), value); octstr_destroy(name); octstr_destroy(value); octstr_destroy(line); return cgwop; } if (octstr_compare(name, octstr_imm("op")) == 0) { /* check different ops */ if (octstr_compare(value, octstr_imm("msg")) == 0) op = CGW_OP_MSG; else if (octstr_compare(value, octstr_imm("ok")) == 0) op = CGW_OP_OK; else if (octstr_compare(value, octstr_imm("delivery")) == 0) op = CGW_OP_DELIVERY; else if (octstr_compare(value, octstr_imm("err")) == 0) op = CGW_OP_ERR; else if (octstr_compare(value, octstr_imm("status")) == 0) op = CGW_OP_STATUS; else info(0, "CGW: Received unknown op: %s", octstr_get_cstr(value)); if (cgwop == NULL) cgwop = cgwop_create(op, 0); else info(0, "cgw: cgwop != null"); } if (op != CGW_OP_NOP) { /* All commands have to be inside an op:xx ... end:xx statement */ if (octstr_compare(name, octstr_imm("end")) == 0) { /* found end of op */ finished = 1; } else { /* store in name/value fields in cgwop */ if (cgwop != NULL) { cgwop_add(cgwop, name, value); } } } octstr_destroy(name); octstr_destroy(value); octstr_destroy(line); if (!finished) line = conn_read_line(server); } else { info(0, "cgw: Received invalid input: %s", octstr_get_cstr(line)); octstr_destroy(line); finished = 1; } } while (!finished); return cgwop; }