📄 wap-appl.c
字号:
warning(0, "WSP: Device doesn't support charset <%s> neither UTF-8", octstr_get_cstr(charset)); } else { /* convert to utf-8 */ debug("wsp",0,"Converting wml/xhtml from charset <%s> to UTF-8", octstr_get_cstr(charset)); if (charset_convert(content.body, octstr_get_cstr(charset), "UTF-8") >= 0) { octstr_destroy(content.charset); content.charset = octstr_create("UTF-8"); /* XXX it might be good idea to change <?xml...encoding?> */ } } } /* convert to iso-8859-1 if original charset is not iso * and device supports it */ else if (octstr_case_compare(charset, octstr_imm("ISO-8859-1")) < 0 && !http_charset_accepted(device_headers, octstr_get_cstr(charset))) { if (!http_charset_accepted(device_headers, "ISO-8859-1")) { warning(0, "WSP: Device doesn't support charset <%s> neither ISO-8859-1", octstr_get_cstr(charset)); } else { /* convert to iso-latin1 */ debug("wsp",0,"Converting wml/xhtml from charset <%s> to ISO-8859-1", octstr_get_cstr(charset)); if (charset_convert(content.body, octstr_get_cstr(charset), "ISO-8859-1") >= 0) { octstr_destroy(content.charset); content.charset = octstr_create("ISO-8859-1"); /* XXX it might be good idea to change <?xml...encoding?> */ } } } octstr_destroy(charset); } /* set WBXML Encoding-Version for wml->wmlc conversion */ if (sm != NULL) { content.version = http_header_value(sm->http_headers, octstr_imm("Encoding-Version")); } else { content.version = NULL; } /* convert content-type by our own converter table */ converted = convert_content(&content, device_headers, octstr_compare(method, octstr_imm("HEAD")) == 0); if (converted < 0) { warning(0, "WSP: All converters for `%s' at `%s' failed.", octstr_get_cstr(content.type), octstr_get_cstr(url)); /* * Don't change status; just send the client what we did get. * Or if smart error messages are configured, send a wmlc deck * with accurate information. */ if (wsp_smart_errors) { octstr_destroy(content.body); octstr_destroy(content.charset); content.body = error_converting(url, content.type); content.charset = octstr_create("UTF-8"); debug("wap.wsp",0,"WSP: returning smart error WML deck for failed converters"); converted = convert_content(&content, device_headers, 0); if (converted == 1) http_header_mark_transformation(headers, content.body, content.type); } } else if (converted == 1) { http_header_mark_transformation(headers, content.body, content.type); /* * set referer URL to WSPMachine, but only if this was a converted * content-type, like .wml */ if (session_id != -1) { debug("wap.wsp.http",0,"WSP: Setting Referer URL to <%s>", octstr_get_cstr(url)); if ((sm = find_session_machine_by_id(session_id)) != NULL) { set_referer_url(url, sm); } else { error(0,"WSP: Failed to find session machine for ID %ld", session_id); } } } /* if converted == 0 then we pass the content wihtout modification */ } if (headers == NULL) headers = http_create_empty_headers(); http_remove_hop_headers(headers); http_header_remove_all(headers, "X-WAP.TOD"); if (x_wap_tod) add_x_wap_tod(headers); if (content.body == NULL) content.body = octstr_create(""); /* * Deal with otherwise wap-aware servers that return text/html error * messages if they report an error. * (Normally we leave the content type alone even if the client doesn't * claim to accept it, because the server might know better than the * gateway.) */ if (http_status_class(status) != HTTP_STATUS_SUCCESSFUL && !http_type_accepted(request_headers, octstr_get_cstr(content.type))) { warning(0, "WSP: Content type <%s> not supported by client," " deleting body.", octstr_get_cstr(content.type)); octstr_destroy(content.body); content.body = octstr_create(""); octstr_destroy(content.type); content.type = octstr_create("text/plain"); http_header_mark_transformation(headers, content.body, content.type); } /* remove body if request method was HEAD, we act strictly here */ else if (octstr_compare(method, octstr_imm("HEAD")) == 0) { octstr_destroy(content.body); content.body = octstr_create(""); /* change to text/plain if received content-type is not accepted */ if (!http_type_accepted(request_headers, "*/*") && !http_type_accepted(request_headers, octstr_get_cstr(content.type))) { octstr_destroy(content.type); content.type = octstr_create("text/plain"); } debug("wsp",0,"WSP: HEAD request, removing body, content-type is now <%s>", octstr_get_cstr(content.type)); http_header_mark_transformation(headers, content.body, content.type); }#ifdef ENABLE_NOT_ACCEPTED /* Returns HTTP response 406 if content-type is not supported by device */ else if (request_headers && content.type && !http_type_accepted(request_headers, octstr_get_cstr(content.type)) && !http_type_accepted(request_headers, "*/*")) { warning(0, "WSP: content-type <%s> not supported", octstr_get_cstr(content.type)); status = HTTP_NOT_ACCEPTABLE; octstr_destroy(content.type); content.type = octstr_create("text/plain"); octstr_destroy(content.charset); octstr_destroy(content.body); content.charset = octstr_create(""); content.body = octstr_create(""); http_header_mark_transformation(headers, content.body, content.type); }#endif /* * If the response is too large to be sent to the client, * suppress it and inform the client. */ if (octstr_len(content.body) > sdu_size && sdu_size > 0) { /* * Only change the status if it indicated success. * If it indicated an error, then that information is * more useful to the client than our "Bad Gateway" would be. * The too-large body is probably an error page in html. */ /* XXX add WSP smart messaging here too */ if (http_status_class(status) == HTTP_STATUS_SUCCESSFUL) status = HTTP_BAD_GATEWAY; warning(0, "WSP: Entity at %s too large (size %ld B, limit %lu B)", octstr_get_cstr(url), octstr_len(content.body), sdu_size); octstr_destroy(content.body); content.body = octstr_create(""); http_header_mark_transformation(headers, content.body, content.type); } if (orig_event->type == S_MethodInvoke_Ind) { return_session_reply(orig_event->u.S_MethodInvoke_Ind.server_transaction_id, status, headers, content.body, session_id); } else { return_unit_reply(orig_event->u.S_Unit_MethodInvoke_Ind.addr_tuple, orig_event->u.S_Unit_MethodInvoke_Ind.transaction_id, status, headers, content.body); } octstr_destroy(content.version); /* body was re-used above */ octstr_destroy(content.type); /* body was re-used above */ octstr_destroy(content.charset); octstr_destroy(url); /* same as content.url */ counter_decrease(fetches);}/* * This thread receives replies from HTTP layer and sends them back to * the phone. */static void return_replies_thread(void *arg){ Octstr *body; struct request_data *p; int status; Octstr *final_url; List *headers; while (run_status == running) { p = http_receive_result(caller, &status, &final_url, &headers, &body); if (p == NULL) break; return_reply(status, body, headers, p->client_SDU_size, p->event, p->session_id, p->method, p->url, p->x_wap_tod, p->request_headers); wap_event_destroy(p->event); http_destroy_headers(p->request_headers); gw_free(p); octstr_destroy(final_url); }}/* * This WML deck is returned when the user asks for the magic * URL "kannel:alive". */#define HEALTH_DECK \ "<?xml version=\"1.0\"?>" \ "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD 1.1//EN\" " \ "\"http://www.wapforum.org/DTD/wml_1.1.xml\">" \ "<wml><card id=\"health\"><p>Ok</p></card></wml>"static void start_fetch(WAPEvent *event) { int ret; long client_SDU_size; /* 0 means no limit */ Octstr *url; List *session_headers; List *request_headers; List *actual_headers; List *resp_headers; WAPAddrTuple *addr_tuple; long session_id; Octstr *content_body; Octstr *method; /* type of request, normally a get or a post */ Octstr *request_body; int x_wap_tod; /* X-WAP.TOD header was present in request */ Octstr *magic_url; struct request_data *p; Octstr *send_msisdn_query, *send_msisdn_header, *send_msisdn_format; int accept_cookies; counter_increase(fetches); if (event->type == S_MethodInvoke_Ind) { struct S_MethodInvoke_Ind *p; /* WSP, connection orientated */ p = &event->u.S_MethodInvoke_Ind; session_headers = p->session_headers; request_headers = p->request_headers; url = octstr_duplicate(p->request_uri); addr_tuple = p->addr_tuple; session_id = p->session_id; client_SDU_size = p->client_SDU_size; request_body = octstr_duplicate(p->request_body); method = p->method; } else { struct S_Unit_MethodInvoke_Ind *p; /* WDP, non orientated */ p = &event->u.S_Unit_MethodInvoke_Ind; session_headers = NULL; request_headers = p->request_headers; url = octstr_duplicate(p->request_uri); addr_tuple = p->addr_tuple; session_id = -1; client_SDU_size = 0; /* No limit */ request_body = octstr_duplicate(p->request_body); method = p->method; } info(0, "Fetching <%s>", octstr_get_cstr(url)); /* * XXX this URL mapping needs to be rebuild! st. */ /* try to rewrite URL */ wap_map_url(&url, &send_msisdn_query, &send_msisdn_header, &send_msisdn_format, &accept_cookies); /* if no mapping found, then use our RADIUS acct proxy header */ if (send_msisdn_header == NULL) send_msisdn_header = octstr_create("X-WAP-Network-Client-MSISDN"); actual_headers = list_create(); if (session_headers != NULL) http_header_combine(actual_headers, session_headers); if (request_headers != NULL) http_header_combine(actual_headers, request_headers); x_wap_tod = http_header_remove_all(actual_headers, "X-WAP.TOD"); add_accept_headers(actual_headers); add_charset_headers(actual_headers); add_network_info(actual_headers, addr_tuple); add_client_sdu_size(actual_headers, client_SDU_size); add_via(actual_headers);#ifdef ENABLE_COOKIES /* DAVI: to finish - accept_cookies -1, * use global accept-cookies, 0 = no, 1 = yes ? */ if (accept_cookies != 0 && (session_id != -1) && /* DAVI (set_cookies(url, actual_headers, find_session_machine_by_id(session_id)) == -1)) */ (set_cookies(actual_headers, find_session_machine_by_id(session_id)) == -1)) error(0, "WSP: Failed to add cookies");#endif /* set referer URL to HTTP header from WSPMachine */ /* * XXX This makes Open Group's test suite wml/events/tasks/go/5 failing, * which requires that device is *not* sending referer, but Kannel drops * it in. We have to remove this for now. */ /* if (session_id != -1) { if ((referer_url = get_referer_url(find_session_machine_by_id(session_id))) != NULL) { add_referer_url(actual_headers, referer_url); } } */ add_kannel_version(actual_headers); add_session_id(actual_headers, session_id); add_msisdn(actual_headers, addr_tuple, send_msisdn_header); octstr_destroy(send_msisdn_query); octstr_destroy(send_msisdn_header); octstr_destroy(send_msisdn_format); http_remove_hop_headers(actual_headers); http_header_pack(actual_headers); magic_url = octstr_imm("kannel:alive"); /* check if this request is a call for our magic URL */ if (octstr_str_compare(method, "GET") == 0 && octstr_compare(url, magic_url) == 0) { ret = HTTP_OK; resp_headers = list_create(); http_header_add(resp_headers, "Content-Type", "text/vnd.wap.wml"); content_body = octstr_create(HEALTH_DECK); octstr_destroy(request_body); return_reply(ret, content_body, resp_headers, client_SDU_size, event, session_id, method, url, x_wap_tod, actual_headers); wap_event_destroy(event); http_destroy_headers(actual_headers); } /* otherwise it should be a GET, POST or HEAD request type */ else if (octstr_str_compare(method, "GET") == 0 || octstr_str_compare(method, "POST") == 0 || octstr_str_compare(method, "HEAD") == 0) { /* we don't allow a body within a GET or HEAD request */ if (request_body != NULL && (octstr_str_compare(method, "GET") == 0 || octstr_str_compare(method, "HEAD") == 0)) { octstr_destroy(request_body); request_body = NULL; } /* * Call deconvert_content() here for transformations of binary * encoded POST requests from the client into plain text decoded * POST requests for the HTTP server. * Mainly this is used for multipart/form-data transmissions, * including MMS on-the-fly message decoding. * When we are doing mms, the phone POSTs contents and acknowled- * gements. In this case, we dont do not deconvert anything. */ if (octstr_str_compare(method, "POST") == 0 && request_body && octstr_len(request_body)) { struct content content; int converted; http_header_get_content_type(actual_headers, &content.type, &content.charset); content.body = request_body; converted = deconvert_content(&content); if (converted == 1) http_header_mark_transformation(actual_headers, content.body, content.type); request_body = content.body; octstr_destroy(content.type); octstr_destroy(content.charset); } /* struct that is used for the HTTP response identifier */ p = gw_malloc(sizeof(*p)); p->client_SDU_size = client_SDU_size; p->event = event; p->session_id = session_id; p->method = method; p->url = url; p->x_wap_tod = x_wap_tod; p->request_headers = actual_headers; /* issue the request to the HTTP server */ http_start_request(caller, http_name2method(method), url, actual_headers, request_body, 0, p, NULL); octstr_destroy(request_body); } /* we don't support the WSP/HTTP method the client asked us */ else { error(0, "WSP: Method %s not supported.", octstr_get_cstr(method)); content_body = octstr_create(""); resp_headers = http_create_empty_headers(); ret = HTTP_NOT_IMPLEMENTED; octstr_destroy(request_body); return_reply(ret, content_body, resp_headers, client_SDU_size, event, session_id, method, url, x_wap_tod, actual_headers); wap_event_destroy(event); http_destroy_headers(actual_headers); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -