/* * Re-escape SMASI ASCII representation of binary data with the * original binary data octet string. * XXX this may be done by the internal parser routines too. */ static void decode_binary_data(Octstr *data) { long pos = 0; while (pos < octstr_len(data)) { int check = octstr_get_char(data, pos); if (check == ':') { Octstr *byte; int msb = octstr_get_char(data, pos + 1); int lsb = octstr_get_char(data, pos + 2); if (msb != -1 && lsb != -1) { byte = octstr_create(""); octstr_append_char(byte, msb); octstr_append_char(byte, lsb); if (octstr_hex_to_binary(byte) != -1) { /* Do inplace unescaping. */ octstr_delete(data, pos, 3); octstr_insert(data, byte, pos); } else { error(0, "Malformed binary encoded data."); } octstr_destroy(byte); } } pos++; } }
/* 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); }
/* * Unescapes incoming message body data by replacing occurrences of escaped * chars with their original character representation. */ static void unescape_data(Octstr *data) { long pos = 0; /* Again, an inplace transformation is used. Because, again, it is * assumed that only a fraction of chars has to be unescaped. */ while (pos < octstr_len(data)) { int check = octstr_get_char(data, pos); if (check == ':') { char byte = 0; int msb = octstr_get_char(data, pos + 1); int lsb = octstr_get_char(data, pos + 2); if (msb == '0') msb = 0; else if (msb >= '1' && msb <= '9') msb -= '1' + 1; else msb -= 'a' + 10; if (lsb == '0') lsb = 0; else if (lsb >= '1' && lsb <= '9') lsb -= '1' + 1; else lsb -= 'a' + 10; byte = msb << 4 | lsb; /* Do inplace unescaping. */ octstr_delete(data, pos, 3); octstr_insert_data(data, pos, &byte, 1); } pos++; } }
static int is_default_cap(Capability *cap) { unsigned long ui; /* All unknown values are empty by default */ if (cap->name != NULL || cap->id < 0 || cap->id >= WSP_NUM_CAPS) return cap->data == NULL || octstr_len(cap->data) == 0; switch (cap->id) { case WSP_CAPS_CLIENT_SDU_SIZE: case WSP_CAPS_SERVER_SDU_SIZE: return (cap->data != NULL && octstr_extract_uintvar(cap->data, &ui, 0) >= 0 && ui == 1400); case WSP_CAPS_PROTOCOL_OPTIONS: return cap->data != NULL && octstr_get_char(cap->data, 0) == 0; case WSP_CAPS_METHOD_MOR: case WSP_CAPS_PUSH_MOR: return cap->data != NULL && octstr_get_char(cap->data, 0) == 1; case WSP_CAPS_EXTENDED_METHODS: case WSP_CAPS_HEADER_CODE_PAGES: case WSP_CAPS_ALIASES: return cap->data == NULL || octstr_len(cap->data) == 0; default: return 0; } }
/** * Convert octet string in GSM format to UTF-8. * Every GSM character can be represented with unicode, hence nothing will * be lost. Escaped charaters will be translated into appropriate UTF-8 character. */ void charset_gsm_to_utf8(Octstr *ostr) { long pos, len; Octstr *newostr; if (ostr == NULL) return; newostr = octstr_create(""); len = octstr_len(ostr); for (pos = 0; pos < len; pos++) { int c, i; c = octstr_get_char(ostr, pos); if (c > 127) { warning(0, "Could not convert GSM (0x%02x) to Unicode.", c); continue; } if(c == 27 && pos + 1 < len) { c = octstr_get_char(ostr, ++pos); for (i = 0; gsm_esctouni[i].gsmesc >= 0; i++) { if (gsm_esctouni[i].gsmesc == c) break; } if (gsm_esctouni[i].gsmesc == c) { /* found a value for escaped char */ c = gsm_esctouni[i].unichar; } else { /* nothing found, look esc in our table */ c = gsm_to_unicode[27]; pos--; } } else if (c < 128) { c = gsm_to_unicode[c]; } /* unicode to utf-8 */ if(c < 128) { /* 0-127 are ASCII chars that need no conversion */ octstr_append_char(newostr, c); } else { /* test if it can be converterd into a two byte char */ if(c < 0x0800) { octstr_append_char(newostr, ((c >> 6) | 0xC0) & 0xFF); /* add 110xxxxx */ octstr_append_char(newostr, (c & 0x3F) | 0x80); /* add 10xxxxxx */ } else { /* else we encode with 3 bytes. This only happens in case of euro symbol */ octstr_append_char(newostr, ((c >> 12) | 0xE0) & 0xFF); /* add 1110xxxx */ octstr_append_char(newostr, (((c >> 6) & 0x3F) | 0x80) & 0xFF); /* add 10xxxxxx */ octstr_append_char(newostr, ((c & 0x3F) | 0x80) & 0xFF); /* add 10xxxxxx */ } /* There are no 4 bytes encoded characters in GSM charset */ }
static long parse_terminator(Octstr *mime_content, long pos) { if (is_cr(octstr_get_char(mime_content, pos))) ++pos; else return -1; if (is_lf(octstr_get_char(mime_content, pos))) ++pos; else return -1; return pos; }
int date_parse_iso (struct universaltime *ut, Octstr *os) { long pos = 0; int c; /* assign defaults */ ut->month = 0; ut->day = 1; ut->hour = 0; ut->minute = 0; ut->second = 0; if ((pos = octstr_parse_long(&(ut->year), os, pos, 10)) < 0) return -1; if (ut->year < 70) ut->year += 2000; else if (ut->year < 100) ut->year += 1900; while ((c = octstr_get_char(os, pos)) != -1 && !gw_isdigit(c)) pos++; if ((pos = octstr_parse_long(&(ut->month), os, pos, 10)) < 0) return 0; /* 0-based months */ if (ut->month > 0) ut->month--; while ((c = octstr_get_char(os, pos)) != -1 && !gw_isdigit(c)) pos++; if ((pos = octstr_parse_long(&(ut->day), os, pos, 10)) < 0) return 0; while ((c = octstr_get_char(os, pos)) != -1 && !gw_isdigit(c)) pos++; if ((pos = octstr_parse_long(&(ut->hour), os, pos, 10)) < 0) return 0; while ((c = octstr_get_char(os, pos)) != -1 && !gw_isdigit(c)) pos++; if ((pos = octstr_parse_long(&(ut->minute), os, pos, 10)) < 0) return 0; while ((c = octstr_get_char(os, pos)) != -1 && !gw_isdigit(c)) pos++; if ((pos = octstr_parse_long(&(ut->second), os, pos, 10)) < 0) return 0; return 0; }
/* * Extension headers are defined in rfc 822, Appendix D, as fields. We must * parse all rfc 822 headers containing a string "Content". These headers * are optional, too. For general definition of message parts see chapter 4.1. * Specifically: "everything after first null line is message body". */ static int drop_extension_headers(Octstr **body_part, Octstr *boundary) { long content_pos, next_header_pos; long next_content_part_pos; next_content_part_pos = octstr_case_search(*body_part, boundary, 0); do { if ((content_pos = octstr_case_nsearch(*body_part, octstr_imm("Content"), 0, next_content_part_pos)) < 0) return 1; if ((next_header_pos = parse_field_name(*body_part, content_pos)) < 0) return 0; if ((next_header_pos = parse_field_value(*body_part, next_header_pos)) < 0) return 0; if ((next_header_pos = parse_terminator(*body_part, next_header_pos)) == 0) return 0; } while (islwspchar(octstr_get_char(*body_part, next_header_pos))); octstr_delete(*body_part, content_pos, next_header_pos - content_pos); return 1; }
static long parse_transport_padding(Octstr *mime_content, long pos) { while (islwspchar(octstr_get_char(mime_content, pos))) ++pos; return pos; }
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; }
/* * Read some headers, i.e., until the first empty line (read and discard * the empty line as well). Return -1 for error, 0 for all headers read. */ static int read_mime_headers(ParseContext *context, List *headers) { Octstr *line, *prev; if (gwlist_len(headers) == 0) prev = NULL; else prev = gwlist_get(headers, gwlist_len(headers) - 1); for (;;) { line = parse_get_line(context); if (line == NULL) { return -1; } if (octstr_len(line) == 0) { octstr_destroy(line); break; } if (isspace(octstr_get_char(line, 0)) && prev != NULL) { octstr_append(prev, line); octstr_destroy(line); } else { gwlist_append(headers, line); prev = line; } } return 0; }
/* * Will replace a binary data octet string (inplace) with a SMASI conform * ASCII representation of the data. */ static void encode_binary_data(Octstr *data) { Octstr *result = octstr_create(""); long pos = 0; while (pos < octstr_len(data)) { int encode = octstr_get_char(data, pos); int msb = (encode & 0xf0) >> 4; int lsb = (encode & 0x0f) >> 0; if (msb == 0) msb = '0'; else if (msb < 10) msb = '1' + msb - 1; else msb = 'a' + msb - 10; if (lsb == 0) lsb = '0'; else if (lsb < 10) lsb = '1' + lsb - 1; else lsb = 'a' + lsb - 10; octstr_append_char(result, ':'); octstr_append_char(result, msb); octstr_append_char(result, lsb); pos++; } /* Replace binary data octet string with ASCII representation. */ octstr_delete(data, 0, octstr_len(data)); octstr_append(data, result); octstr_destroy(result); }
/* * Escapes outgoing message body data by replacing occurrences of "special" * chars inside the octet string. */ static void escape_data(Octstr *data) { long pos = 0; /* This one uses a different approach than the encode and decode * functions. Because it is assumed, that only a fraction of the * contained chars have to be escaped. */ while (pos < octstr_len(data)) { Octstr * escaped = NULL; int check = octstr_get_char(data, pos); if (check == ':') escaped = colon; else if (check == '=') escaped = assign; else if (check == ',') escaped = comma; else if (check == '\n') escaped = cr; else if (check == '\r') escaped = lf; if (escaped != NULL) { /* If the current char has to be escaped, delete the char from * the source string, replace it with the escape sequence, and * advance position until after the inserted sequence. */ octstr_delete(data, pos, 1); octstr_insert(data, escaped, pos); pos += octstr_len(escaped); } else { /* If not escaped, simply skip the current char. */ pos++; } } }
static void send_packet(Octstr *out, int opcode, int sequence, ...) { va_list ap; int parm; unsigned char *value; int checksum; int old_len, new_len; if (activity == ACT_listen) return; old_len = octstr_len(out); octstr_format_append(out, "%c%02d:%03d%c", STX, opcode, sequence, TAB); va_start(ap, sequence); for (parm = va_arg(ap, int); parm != 0; parm = va_arg(ap, int)) { value = va_arg(ap, unsigned char *); octstr_format_append(out, "%03d:%s\11", parm, value); } va_end(ap); /* Calculate checksum */ checksum = 0; for (new_len = octstr_len(out); old_len < new_len; old_len++) { checksum = (checksum + octstr_get_char(out, old_len)) & 0xff; } octstr_format_append(out, "%02X%c", checksum, ETX); }
static int eat_char(Octstr *packet, int ch) { if (octstr_get_char(packet, 0) == ch) { octstr_delete(packet, 0, 1); return 0; } return -1; }
Octstr *html_to_sms(Octstr *html) { long i, len; int c; Octstr *sms; sms = octstr_create(""); len = octstr_len(html); i = 0; while (i < len) { c = octstr_get_char(html, i); switch (c) { case '<': if (html_comment_begins(html, i)) skip_html_comment(html, &i); else skip_html_tag(html, &i); break; case '&': convert_html_entity(sms, html, &i); break; default: octstr_append_char(sms, c); ++i; break; } } octstr_shrink_blanks(sms); octstr_strip_blanks(sms); return sms; }
int main() { Octstr *os; long i; gw_prioqueue_t *queue; gwlib_init(); /* os = octstr_imm("iareanmsgotx"); */ os = octstr_imm("123456789"); queue = gw_prioqueue_create(my_cmp); for (i=0; i < octstr_len(os); i++) { char a[2]; a[0] = octstr_get_char(os, i); a[1] = '\0'; gw_prioqueue_insert(queue, octstr_create(a)); } gw_prioqueue_foreach(queue, my_dump); while ((os = gw_prioqueue_remove(queue))) { debug("", 0, "%s", octstr_get_cstr(os)); octstr_destroy(os); } debug("", 0, "gw_prioqueue_len=%ld", gw_prioqueue_len(queue)); gwlib_shutdown(); return 0; }
static Octstr *radius_type_convert(int type, Octstr *value) { Octstr *ret = NULL; int i; switch (type) { case t_int: ret = octstr_format("%ld", decode_integer(value, 0, 4)); break; case t_string: ret = octstr_format("%s", octstr_get_cstr(value)); break; case t_ipaddr: ret = octstr_create(""); for (i = 0; i < 4; i++) { int c = octstr_get_char(value, i); Octstr *b = octstr_format("%d", c); octstr_append(ret, b); if (i < 3) octstr_append_cstr(ret, "."); octstr_destroy(b); } break; default: panic(0, "RADIUS: Attribute type %d does not exist.", type); break; } return ret; }
static void eat_checksum(Octstr *packet) { int len; int ch1, ch2, ch3; len = octstr_len(packet); if (len < 3) return; ch1 = octstr_get_char(packet, len - 3); ch2 = octstr_get_char(packet, len - 2); ch3 = octstr_get_char(packet, len - 1); if (isxdigit(ch3) && isxdigit(ch2) && ch1 == TAB) octstr_delete(packet, len - 3, 3); }
/* 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); }
void wap_map_url(Octstr **osp, Octstr **send_msisdn_query, Octstr **send_msisdn_header, Octstr **send_msisdn_format, int *accept_cookies) { long i; Octstr *newurl, *tmp1, *tmp2; newurl = tmp1 = tmp2 = NULL; *send_msisdn_query = *send_msisdn_header = *send_msisdn_format = NULL; *accept_cookies = -1; debug("wsp",0,"WSP: Mapping url <%s>", octstr_get_cstr(*osp)); for (i = 0; url_map && i < gwlist_len(url_map); i++) { struct url_map_struct *entry; entry = gwlist_get(url_map, i); /* debug("wsp",0,"WSP: matching <%s> with <%s>", octstr_get_cstr(entry->url), octstr_get_cstr(entry->map_url)); */ /* DAVI: I only have '*' terminated entry->url implementation for now */ tmp1 = octstr_duplicate(entry->url); octstr_delete(tmp1, octstr_len(tmp1)-1, 1); /* remove last '*' */ tmp2 = octstr_copy(*osp, 0, octstr_len(tmp1)); debug("wsp",0,"WSP: Matching <%s> with <%s>", octstr_get_cstr(tmp1), octstr_get_cstr(tmp2)); if (octstr_case_compare(tmp2, tmp1) == 0) { /* rewrite url if configured to do so */ if (entry->map_url != NULL) { if (octstr_get_char(entry->map_url, octstr_len(entry->map_url)-1) == '*') { newurl = octstr_duplicate(entry->map_url); octstr_delete(newurl, octstr_len(newurl)-1, 1); octstr_append(newurl, octstr_copy(*osp, octstr_len(entry->url)-1, octstr_len(*osp)-octstr_len(entry->url)+1)); } else { newurl = octstr_duplicate(entry->map_url); } debug("wsp",0,"WSP: URL Rewriten from <%s> to <%s>", octstr_get_cstr(*osp), octstr_get_cstr(newurl)); octstr_destroy(*osp); *osp = newurl; } *accept_cookies = entry->accept_cookies; *send_msisdn_query = octstr_duplicate(entry->send_msisdn_query); *send_msisdn_header = octstr_duplicate(entry->send_msisdn_header); *send_msisdn_format = octstr_duplicate(entry->send_msisdn_format); octstr_destroy(tmp1); octstr_destroy(tmp2); break; } octstr_destroy(tmp1); octstr_destroy(tmp2); } }
/* * Remove the first word and the whitespace that follows it from * the start of the message data. */ static void strip_keyword(Msg *request) { int ch; long pos; pos = 0; for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++) if (isspace(ch)) break; for (; (ch = octstr_get_char(request->sms.msgdata, pos)) >= 0; pos++) if (!isspace(ch)) break; octstr_delete(request->sms.msgdata, 0, pos); }
static Octstr *get_start_param(Octstr *content_type) { Octstr *start; int len; if (!content_type) return NULL; start = http_get_header_parameter(content_type, octstr_imm("start")); if (start && (len = octstr_len(start)) > 0 && octstr_get_char(start, 0) == '"' && octstr_get_char(start, len-1) == '"') { octstr_delete(start, 0, 1); octstr_delete(start, len-2, 1); } return start; }
static void fixup_value(Octstr *value, int lineno) { Octstr *tmp; int i,n; octstr_strip_blanks(value); if (octstr_get_char(value, 0) != '"') return; if (octstr_get_char(value, octstr_len(value) - 1) != '"') mms_error(0, "mms_cfg", NULL, "Missing enclosing '\"' at line %d in conf file", lineno); octstr_delete(value, 0,1); /* strip quotes. */ octstr_delete(value, octstr_len(value) - 1, 1); tmp = octstr_duplicate(value); octstr_delete(value, 0, octstr_len(value)); for (i = 0, n = octstr_len(tmp); i < n; i++) { int ch = octstr_get_char(tmp, i); if (ch != '\\') { octstr_append_char(value, ch); continue; } i++; /* skip forward. */ ch = octstr_get_char(tmp,i); switch(ch) { case '"': case '\\': default: octstr_append_char(value, ch); break; case 'n': octstr_append_char(value, '\n'); break; case 't': octstr_append_char(value, '\t'); break; } } octstr_destroy(tmp); }
static void parse_value(Octstr *value) { Octstr *temp; long len; int c; octstr_strip_blanks(value); len = octstr_len(value); if (octstr_get_char(value, 0) != '"' || octstr_get_char(value, len - 1) != '"') return; octstr_delete(value, len - 1, 1); octstr_delete(value, 0, 1); temp = octstr_duplicate(value); octstr_truncate(value, 0); while (octstr_len(temp) > 0) { c = octstr_get_char(temp, 0); octstr_delete(temp, 0, 1); if (c != '\\' || octstr_len(temp) == 0) octstr_append_char(value, c); else { c = octstr_get_char(temp, 0); octstr_delete(temp, 0, 1); switch (c) { case '\\': case '"': octstr_append_char(value, c); break; default: octstr_append_char(value, '\\'); octstr_append_char(value, c); break; } } } octstr_destroy(temp); }
static void octstr_drop_trailing_zeros(Octstr **date_token) { while (1) { if (octstr_get_char(*date_token, octstr_len(*date_token) - 1) == '\0') octstr_delete(*date_token, octstr_len(*date_token) - 1, 1); else return; } }
static List *make_mm_flags(List *oflags, List *flag_cmds) { List *l = oflags ? oflags : gwlist_create(); int i, n; for (i = 0, n = gwlist_len(l); i < n; i++) { /* cleanup list. */ Octstr *x = gwlist_get(l,i); int ch = octstr_get_char(x, 0); if (ch == '+' || ch == '-' || ch == '/') octstr_delete(x,0,1); } for (i = 0, n = (flag_cmds ? gwlist_len(flag_cmds) : 0); i<n; i++) { Octstr *x = gwlist_get(flag_cmds,i); int ch = octstr_get_char(x, 0); char *s = octstr_get_cstr(x); int j, m, cmd; if (ch == '+' || ch == '-' || ch == '/') { s++; cmd = ch; } else cmd = '+'; /* Find it in original. If existent, remove it. */ for (j = 0, m = gwlist_len(l); j < m; j++) if (octstr_str_compare(gwlist_get(l,j),s) == 0) { Octstr *y = gwlist_get(l,j); gwlist_delete(l,j,1); octstr_destroy(y); j--; m--; } if (cmd == '+' || cmd == '/') gwlist_append(l, octstr_create(s)); } return l; }
int parse_get_char(ParseContext *context) { gw_assert(context != NULL); if (context->pos == context->limit) { context->error = 1; return -1; } return octstr_get_char(context->data, context->pos++); }
static long parse_field_name(Octstr *content, long pos) { while (octstr_get_char(content, pos) != ':' && pos < octstr_len(content)) ++pos; if (pos == octstr_len(content)) return -1; return pos; }
static unsigned long get_varint(Octstr *pdu, int pos) { int c; long result = 0; do { c = octstr_get_char(pdu, pos++); result = (result << 7) | (c & 0x7f); } while (c & 0x80); return c; }