📄 wap-appl.c
字号:
* Note: if request is HEAD, body is empty and we still need to adapt * content-type but we don't need to convert a 0 bytes body */ if (allow_empty && octstr_len(content->body) == 0) return 1; new_body = converters[i].convert(content); if (new_body != NULL) { long s = octstr_len(content->body); octstr_destroy(content->body); octstr_destroy(content->type); content->body = new_body; content->type = octstr_create(converters[i].result_type); debug("wap.convert",0,"WSP: Content-type is " "now <%s>, size %ld bytes (before: %ld bytes), content body is:", converters[i].result_type, octstr_len(new_body), s); octstr_dump(new_body, 0); return 1; } debug("wap.convert",0,"WSP: Content convertion failed!"); failed = 1; } } return (failed ? -1 : 0);}/* * Tries to deconvert or decompile a specific content-type to * it's complementing one. * Returns 1 if an deconvertion has been successfull, * -1 if an deconvertion failed and 0 if no deconvertion routine * was maching this content-type */static int deconvert_content(struct content *content) { Octstr *new_body; int failed = 0; int i; debug("wap.deconvert",0,"WSP deconvert: Trying to deconvert:"); octstr_dump(content->body, 0); for (i = 0; i < NUM_DECONVERTERS; i++) { if (octstr_str_compare(content->type, deconverters[i].type) == 0) { debug("wap.deconvert",0,"WSP: Deconverting from <%s> to <%s>", octstr_get_cstr(content->type), deconverters[i].result_type); new_body = deconverters[i].deconvert(content); if (new_body != NULL) { long s = octstr_len(content->body); octstr_destroy(content->body); octstr_destroy(content->type); content->body = new_body; content->type = octstr_create(deconverters[i].result_type); debug("wap.convert",0,"WSP: Content-type is " "now <%s>, size %ld bytes (before: %ld bytes), content body is:", deconverters[i].result_type, octstr_len(new_body), s); octstr_dump(new_body, 0); return 1; } debug("wap.deconvert",0,"WSP: Content convertion failed!"); failed = 1; } } return (failed ? -1 : 0);}/* Add a header identifying our gateway version */static void add_kannel_version(List *headers) { http_header_add(headers, "X-WAP-Gateway", GW_NAME "/" GW_VERSION);}/* Add Accept-Charset: headers for stuff the WML compiler can * convert to UTF-8. *//* XXX This is not really correct, since we will not be able * to handle those charsets for all content types, just WML/XHTML. */static void add_charset_headers(List *headers) { long i, len; gw_assert(charsets != NULL); len = list_len(charsets); for (i = 0; i < len; i++) { unsigned char *charset = octstr_get_cstr(list_get(charsets, i)); if (!http_charset_accepted(headers, charset)) http_header_add(headers, "Accept-Charset", charset); }}/* Add Accept: headers for stuff we can convert for the phone */static void add_accept_headers(List *headers) { int i; for (i = 0; i < NUM_CONVERTERS; i++) { if (http_type_accepted(headers, "*/*") || ( http_type_accepted(headers, converters[i].result_type) && !http_type_accepted(headers, converters[i].type))) { http_header_add(headers, "Accept", converters[i].type); } }}/* Add X-WAP-Network-Client-IP: header to proxy client IP to HTTP server */static void add_network_info(List *headers, WAPAddrTuple *addr_tuple) { if (octstr_len(addr_tuple->remote->address) > 0) { http_header_add(headers, "X-WAP-Network-Client-IP", octstr_get_cstr(addr_tuple->remote->address)); }}/* Add X-WAP-Session-ID: header to request */static void add_session_id(List *headers, long session_id) { if (session_id != -1) { char buf[40]; sprintf(buf, "%ld", session_id); http_header_add(headers, "X-WAP-Session-ID", buf); }}/* Add X-WAP-Client-SDU-Size: to provide information on client capabilities */static void add_client_sdu_size(List *headers, long sdu_size) { if (sdu_size > 0) { Octstr *buf; buf = octstr_format("%ld", sdu_size); http_header_add(headers, "X-WAP-Client-SDU-Size", octstr_get_cstr(buf)); octstr_destroy(buf); }}/* Add proxy Via: header to request with our Kannel version */static void add_via(List *headers) { Octstr *os; Octstr *version; version = http_header_value(headers, octstr_imm("Encoding-Version")); os = octstr_format("WAP/%s %S (" GW_NAME "/%s)", (version ? octstr_get_cstr(version) : "1.1"), get_official_name(), GW_VERSION); http_header_add(headers, "Via", octstr_get_cstr(os)); octstr_destroy(os); octstr_destroy(version);}/* * Add an X-WAP.TOD header to the response headers. It is defined in * the "WAP Caching Model" specification. * We generate it in textual form and let WSP header packing convert it * to binary form. */static void add_x_wap_tod(List *headers) { Octstr *gateway_time; gateway_time = date_format_http(time(NULL)); if (gateway_time == NULL) { warning(0, "Could not add X-WAP.TOD response header."); return; } http_header_add(headers, "X-WAP.TOD", octstr_get_cstr(gateway_time)); octstr_destroy(gateway_time);}/* Add MSISDN provisioning information to HTTP header */static void add_msisdn(List *headers, WAPAddrTuple *addr_tuple, Octstr *send_msisdn_header) { Octstr *msisdn = NULL; Octstr *value = NULL; if (send_msisdn_header == NULL || octstr_len(send_msisdn_header) == 0) return; /* * Security considerations. If there are headers with the header name we * use to pass on the MSISDN number, then remove them. */ if ((value = http_header_value(headers, send_msisdn_header)) != NULL) { warning(0, "MSISDN header <%s> already present on request, " "header value=<%s>", octstr_get_cstr(send_msisdn_header), octstr_get_cstr(value)); http_header_remove_all(headers, octstr_get_cstr(send_msisdn_header)); } /* * XXX Add generic msisdn provisioning cleanly in here! * See revision 1.89 for Bruno's try. */ /* We do not accept NULL values to be added to the HTTP header */ if ((msisdn = radius_acct_get_msisdn(addr_tuple->remote->address)) != NULL) { http_header_add(headers, octstr_get_cstr(send_msisdn_header), octstr_get_cstr(msisdn)); } octstr_destroy(value); octstr_destroy(msisdn);}/* XXX DAVI: Disabled in cvs revision 1.81 for Opengroup testsstatic void add_referer_url(List *headers, Octstr *url) { if (octstr_len(url) > 0) { http_header_add(headers, "Referer", octstr_get_cstr(url)); }}*/static void set_referer_url(Octstr *url, WSPMachine *sm){ gw_assert(url != NULL); gw_assert(sm != NULL); octstr_destroy(sm->referer_url); sm->referer_url = octstr_duplicate(url);}static Octstr *get_referer_url(const WSPMachine *sm){ return sm ? sm->referer_url : NULL;}/* * Return the reply from an HTTP request to the phone via a WSP session. */static void return_session_reply(long server_transaction_id, long status, List *headers, Octstr *body, long session_id){ WAPEvent *e; e = wap_event_create(S_MethodResult_Req); e->u.S_MethodResult_Req.server_transaction_id = server_transaction_id; e->u.S_MethodResult_Req.status = status; e->u.S_MethodResult_Req.response_headers = headers; e->u.S_MethodResult_Req.response_body = body; e->u.S_MethodResult_Req.session_id = session_id; wsp_session_dispatch_event(e);}/* * Return the reply from an HTTP request to the phone via connectionless * WSP. */static void return_unit_reply(WAPAddrTuple *tuple, long transaction_id, long status, List *headers, Octstr *body){ WAPEvent *e; e = wap_event_create(S_Unit_MethodResult_Req); e->u.S_Unit_MethodResult_Req.addr_tuple = wap_addr_tuple_duplicate(tuple); e->u.S_Unit_MethodResult_Req.transaction_id = transaction_id; e->u.S_Unit_MethodResult_Req.status = status; e->u.S_Unit_MethodResult_Req.response_headers = headers; e->u.S_Unit_MethodResult_Req.response_body = body; wsp_unit_dispatch_event(e);}/* * Return an HTTP reply back to the phone. */static void return_reply(int status, Octstr *content_body, List *headers, long sdu_size, WAPEvent *orig_event, long session_id, Octstr *method, Octstr *url, int x_wap_tod, List *request_headers){ struct content content; int converted; WSPMachine *sm; List *device_headers; WAPAddrTuple *addr_tuple; Octstr *ua, *server; content.url = url; content.body = content_body; content.version = content.type = content.charset = NULL; server = ua = NULL; /* Get session machine for this session. If this was a connection-less * request be obviously will not find any session machine entry. */ sm = find_session_machine_by_id(session_id); /* ensure we pass only the original headers to the convertion routine */ device_headers = (orig_event->type == S_MethodInvoke_Ind) ? orig_event->u.S_MethodInvoke_Ind.request_headers : orig_event->u.S_Unit_MethodInvoke_Ind.request_headers; if (device_headers == NULL) device_headers = list_create(); /* * We are acting as a proxy. Hence ensure we log a correct HTTP response * code to our access-log file to allow identification of failed proxying * requests in the main accesss-log. */ /* get client IP and User-Agent identifier */ addr_tuple = (orig_event->type == S_MethodInvoke_Ind) ? orig_event->u.S_MethodInvoke_Ind.addr_tuple : orig_event->u.S_Unit_MethodInvoke_Ind.addr_tuple; ua = http_header_value(request_headers, octstr_imm("User-Agent")); if (headers != NULL) { /* get response content type and Server identifier */ http_header_get_content_type(headers, &content.type, &content.charset); server = http_header_value(headers, octstr_imm("Server")); } /* log the access */ /* XXX make this configurable in the future */ alog("%s %s <%s> (%s, charset='%s') %ld %d <%s> <%s>", octstr_get_cstr(addr_tuple->remote->address), octstr_get_cstr(method), octstr_get_cstr(url), content.type ? octstr_get_cstr(content.type) : "", content.charset ? octstr_get_cstr(content.charset) : "", octstr_len(content.body), status < 0 ? HTTP_BAD_GATEWAY : status, ua ? octstr_get_cstr(ua) : "", server ? octstr_get_cstr(server) : ""); octstr_destroy(ua); octstr_destroy(server); if (status < 0) { error(0, "WSP: HTTP lookup failed, oops."); /* smart WSP error messaging?! */ if (wsp_smart_errors) { Octstr *referer_url; status = HTTP_OK; content.type = octstr_create("text/vnd.wap.wml"); content.charset = octstr_create(""); /* * check if a referer for this URL exists and * get back to the previous page in this case */ if ((referer_url = get_referer_url(find_session_machine_by_id(session_id)))) { content.body = error_requesting_back(url, referer_url); debug("wap.wsp",0,"WSP: returning smart error WML deck for referer URL"); } /* * if there is no referer to retun to, check if we have a * device-home defined and return to that, otherwise simply * drop an error wml deck. */ else if (device_home != NULL) { content.body = error_requesting_back(url, device_home); debug("wap.wsp",0,"WSP: returning smart error WML deck for device-home URL"); } else { content.body = error_requesting(url); debug("wap.wsp",0,"WSP: returning smart error WML deck"); } /* * if we did not connect at all there is no content in * the headers list, so create for the upcoming transformation */ if (headers == NULL) headers = http_create_empty_headers(); converted = convert_content(&content, device_headers, 0); if (converted == 1) http_header_mark_transformation(headers, content.body, content.type); } else { /* no WSP smart error messaging */ status = HTTP_BAD_GATEWAY; content.type = octstr_create("text/plain"); content.charset = octstr_create(""); content.body = octstr_create(""); } } else { /* received response by HTTP server */ #ifdef ENABLE_COOKIES if (session_id != -1) /* DAVI if (get_cookies(url, headers, find_session_machine_by_id(session_id)) == -1) */ if (get_cookies(headers, find_session_machine_by_id(session_id)) == -1) error(0, "WSP: Failed to extract cookies");#endif /* * XXX why do we transcode charsets on the content body here?! * Why is this not in the scope of the HTTP server, rather * then doing this inside Kannel?! st. */ /* * Adapts content body's charset to device. * If device doesn't support body's charset but supports UTF-8, this * block tries to convert body to UTF-8. * (This is required for Sharp GX20 for example) */ if (octstr_search(content.type, octstr_imm("text/vnd.wap.wml"), 0) >= 0 || octstr_search(content.type, octstr_imm("application/xhtml+xml"), 0) >= 0 || octstr_search(content.type, octstr_imm("application/vnd.wap.xhtml+xml"), 0) >= 0) { Octstr *charset; /* get charset used in content body, default to utf-8 if not present */ if ((charset = find_charset_encoding(content.body)) == NULL) charset = octstr_imm("UTF-8"); /* convert to utf-8 if original charset is not utf-8 * and device supports it */ if (octstr_case_compare(charset, octstr_imm("UTF-8")) < 0 && !http_charset_accepted(device_headers, octstr_get_cstr(charset))) { if (!http_charset_accepted(device_headers, "UTF-8")) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -