diff --git a/HTTPmsg_CNL113312.tpd b/HTTPmsg_CNL113312.tpd new file mode 100644 index 0000000000000000000000000000000000000000..b8043a7c59b9d39915b3231c4d0216378ab870be --- /dev/null +++ b/HTTPmsg_CNL113312.tpd @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2014 Ericsson + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html + + + File: HTTPmsg_CNL113312.tpd + Description: tpd project file + Rev: R8D + Prodnr: CNL 113 312 + Updated: 2014-09-03 + Contact: http://ttcn.ericsson.se + + --> +<TITAN_Project_File_Information version="1.0"> + <ProjectName>HTTPmsg_CNL113312</ProjectName> + <ReferencedProjects> + <ReferencedProject name="Abstract_Socket_CNL113384" projectLocationURI="../Common_Components/Abstract_Socket_CNL113384/Abstract_Socket_CNL113384.tpd"/> + </ReferencedProjects> + <Folders> + <FolderResource projectRelativePath="doc" relativeURI="doc"/> + <FolderResource projectRelativePath="src" relativeURI="src"/> + </Folders> + <Files> + <FileResource projectRelativePath="doc/HTTPmsg_CNL113312_FS.pdf" relativeURI="doc/HTTPmsg_CNL113312_FS.pdf"/> + <FileResource projectRelativePath="doc/HTTPmsg_CNL113312_PRI.pdf" relativeURI="doc/HTTPmsg_CNL113312_PRI.pdf"/> + <FileResource projectRelativePath="doc/HTTPmsg_CNL113312_UG.pdf" relativeURI="doc/HTTPmsg_CNL113312_UG.pdf"/> + <FileResource projectRelativePath="src/HTTPmsg_MessageLen.ttcn" relativeURI="src/HTTPmsg_MessageLen.ttcn"/> + <FileResource projectRelativePath="src/HTTPmsg_MessageLen_Function.cc" relativeURI="src/HTTPmsg_MessageLen_Function.cc"/> + <FileResource projectRelativePath="src/HTTPmsg_PT.cc" relativeURI="src/HTTPmsg_PT.cc"/> + <FileResource projectRelativePath="src/HTTPmsg_PT.hh" relativeURI="src/HTTPmsg_PT.hh"/> + <FileResource projectRelativePath="src/HTTPmsg_PortType.ttcn" relativeURI="src/HTTPmsg_PortType.ttcn"/> + <FileResource projectRelativePath="src/HTTPmsg_Types.ttcn" relativeURI="src/HTTPmsg_Types.ttcn"/> + </Files> + <ActiveConfiguration>Default</ActiveConfiguration> + <Configurations> + <Configuration name="Default"> + <ProjectProperties> + <MakefileSettings> + <generateInternalMakefile>true</generateInternalMakefile> + <GNUMake>true</GNUMake> + <incrementalDependencyRefresh>true</incrementalDependencyRefresh> + <targetExecutable>bin/HTTPmsg_CNL113312</targetExecutable> + <buildLevel>Level 3 - Creating object files with dependency update</buildLevel> + </MakefileSettings> + <LocalBuildSettings> + <workingDirectory>bin</workingDirectory> + </LocalBuildSettings> + </ProjectProperties> + <FolderProperties> + <FolderResource> + <FolderPath>doc</FolderPath> + <FolderProperties> + <ExcludeFromBuild>true</ExcludeFromBuild> + </FolderProperties> + </FolderResource> + </FolderProperties> + </Configuration> + </Configurations> +</TITAN_Project_File_Information> diff --git a/demo/HTTP_Test.cfg b/demo/HTTP_Test.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0ae719448171cd80bb150e3955ebf460d8c089bf --- /dev/null +++ b/demo/HTTP_Test.cfg @@ -0,0 +1,34 @@ +[LOGGING] +FileMask := LOG_ALL | TTCN_MATCHING | TTCN_DEBUG +ConsoleMask := TTCN_PORTEVENT | TTCN_DEBUG +SourceInfoFormat := Single + +[MODULE_PARAMETERS] +HTTP_Test_no_ASPs.HttpServerHostName := "localhost" +HTTP_Test_no_ASPs.HttpServerPort := 1025 +HTTP_Test_no_ASPs.HTTPClientUseSSL := false +HTTP_Test_no_ASPs.HttpServerListenPort := 1025 +HTTP_Test_no_ASPs.HttpServerUseSSL := false + +[TESTPORT_PARAMETERS] +#system.HTTP_client_port.VERIFYCERTIFICATE := "no" +#system.HTTP_client_port.TRUSTEDCALIST_FILE := "certificates/CAcert.pem" +system.HTTP_client_port.http_debugging := "yes" +system.HTTP_client_port.use_notification_ASPs := "no" +system.HTTP_server_port.use_notification_ASPs := "no" +system.HTTP_server_port.KEYFILE := "/mnt/unix/vobs/ttcn/TCC_Common/TestPorts/HTTPmsg_CNL113312/demo/server.key" +system.HTTP_server_port.CERTIFICATEFILE := "/mnt/unix/vobs/ttcn/TCC_Common/TestPorts/HTTPmsg_CNL113312/demo/server.crt" +system.HTTP_server_port.PASSWORD := "katinka1" +system.HTTP_server_port.TRUSTEDCALIST_FILE := "certificates/CAcert.pem" +system.HTTP_server_port.http_debugging := "yes" + +[MAIN_CONTROLLER] +KillTimer := 1 +TCPPort := 9036 + +[EXECUTE] +#HTTP_Test_no_ASPs.parallel_TC_client +#HTTP_Test_no_ASPs.stress_TC_Persistent_both +#HTTP_Test_no_ASPs.tc_http_encDec +HTTP_Test_no_ASPs.tc_http_encDec2 +//saved by GUI diff --git a/demo/HTTP_Test_no_ASPs.ttcn b/demo/HTTP_Test_no_ASPs.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..3d69543f9bc991777c5fae144ea98844022e8319 --- /dev/null +++ b/demo/HTTP_Test_no_ASPs.ttcn @@ -0,0 +1,409 @@ +// +// File: HTTP_Test_no_ASPs +// Description: To demonstrate how to use the test port +// Rev: R8C +// Prodnr: CNL 113 469 +// Updated: 2007-11-09 +// Contact: http://ttcn.ericsson.se +// Author: ETH/RZX Eduard Czimbalmos +module HTTP_Test_no_ASPs { + +modulepar { + charstring HttpServerHostName := "www.eth.ericsson.se"; + integer HttpServerPort := 80; + boolean HTTPClientUseSSL := false; + integer HttpServerListenPort := 1026; + boolean HttpServerUseSSL := false +} + +import from HTTPmsg_Types all; +import from HTTPmsg_PortType all; + +type component MTC {}; + +type component HTTP_client { + port HTTPmsg_PT HTTP_client_port; +}; + +type component HTTP_server { + port HTTPmsg_PT HTTP_server_port; +}; + +//========================================================================= +// Data Types +//========================================================================= + +type record of charstring CHARSTRINGS; +type record of octetstring OCTETSTRINGS; + +type record of HTTP_client ptcList; + + +template Half_close h := { client_id := ? }; +template HTTPMessage recv_resp := { response := ? }; +template HTTPMessage recv_req := { request := ? }; +template HTTPMessage recv_err := { erronous_msg := ? }; + +function TC() runs on HTTP_client +{ +/* var HeaderLines hd := { {header_name := "Host", header_value := HttpServerHostName}, + {header_name := "Connection", header_value := "close" } }; + var HTTPRequest r := { method := "GET", uri := "/x1.xml", + version_major := 1, version_minor := 1, header := hd, body := omit };*/ + var HeaderLines hd := { {header_name := "Content-Type", header_value := "text/xml"}, + {header_name := "Content-Length", header_value := "508" }, + {header_name := "Expires", header_value := "Sat, 01 Jan 2000 00:00:00 GMT" }, + {header_name := "Pragma", header_value := "no-cache" } }; + var HTTPRequest r := { client_id := omit, method := "POS T", uri := "/", + version_major := 1, version_minor := 0, header := hd, body := "<?xml version='1.0' encoding='ISO-8859-1' standalone='yes'?><!DOCTYPE ANS SYSTEM 'file://mpp50_ans.dtd'><ANS ver=\"5.00\"><PUSH_USER><PUSH_ID>clientPush</PUSH_ID><PUSH_PWD>clientPush</PUSH_PWD></PUSH_USER><LPA><GMT_OFF>+0100</GMT_OFF><POS msid=\"4670112345\"><PD><TIME>20040117132719</TIME><POLYGON><LL_POINT><LAT>N100410</LAT><LONG>E0202020</LONG></LL_POINT><LL_POINT><LAT>N101610</LAT><LONG>E0202620</LONG></LL_POINT><LL_POINT><LAT>N101610</LAT><LONG>E0201420</LONG></LL_POINT></POLYGON></PD></POS></LPA></ANS>" }; + var HTTPMessage send_req := { request := r }; + var Connect conn := { hostname := HttpServerHostName, + portnumber := HttpServerPort, use_ssl := HTTPClientUseSSL }; + var Close c := { client_id := omit }; + + map(self:HTTP_client_port, system:HTTP_client_port); + + var boolean conn_ok := false; + while(conn_ok == false) + { + timer t_connect := 2.0; + t_connect.start; + HTTP_client_port.send(conn); + alt { + [] HTTP_client_port.receive(recv_err) { + timer t_wait := 2.0; + t_wait.start; + t_wait.timeout; } + [] t_connect.timeout { + conn_ok := true; + log("connection to server ok"); } + } + } // endwhile + + timer T_guard := 5.0; + T_guard.start; + HTTP_client_port.send(send_req); + + alt { + [] HTTP_client_port.receive(h) { + HTTP_client_port.send(c); + setverdict(fail); } + [] HTTP_client_port.receive(recv_resp) { + timer t := 10.0; + t.start; + alt { + [] HTTP_client_port.receive(h) { + HTTP_client_port.send(c); + t.stop; + setverdict(pass); } + [] t.timeout { + HTTP_client_port.send(c); + t.stop; + setverdict(fail); } + }; + } + [] HTTP_client_port.receive { + HTTP_client_port.send(c); + setverdict(fail); + } + [] T_guard.timeout { + setverdict(fail); } + }; + + unmap(self:HTTP_client_port, system:HTTP_client_port); +} + +function server_TC() runs on HTTP_server +{ + var Listen listen := { local_hostname := omit, portnumber := HttpServerListenPort, use_ssl := HttpServerUseSSL }; + var HTTPResponse resp := { client_id := omit, version_major := 1, version_minor := 1, statuscode := 200, statustext := "OK", + header := { { header_name := "Server", header_value := "TTCN Test Suite simulated HTTP/1.1 server" }, + { header_name := "Content-Length", header_value := "643" } }, + body := "<?xml version= '1.0' encoding='ISO-8859-1' standalone='yes'?>\n<!DOCTYPE ANS>\n<ANS ver=\"3.00\">\n<LIA>\n<GMT_OFF>+0100</GMT_OFF>\n<POS msid=\"1234512345\">\n<PD>\n<TIME>20000626171825</TIME>\n<ARC>\n<LL_POINT>\n<LAT>N301628</LAT>\n<LONG>W974425</LONG>\n</LL_POINT>\n<IN_RAD>1100</IN_RAD>\n<OUT_RAD>1650</OUT_RAD>\n<START_ANGLE>120</START_ANGLE>\n<STOP_ANGLE>240</STOP_ANGLE>\n</ARC>\n</PD>\n</POS>\n<POS msid=\"1234512346\">\n<PD>\n<TIME>20000626171825</TIME>\n<ARC>\n<LL_POINT>\n<LAT>N301630</LAT>\n<LONG>W974450</LONG>\n</LL_POINT>\n<IN_RAD>0</IN_RAD>\n<OUT_RAD>1650</OUT_RAD>\n<START_ANGLE> 120 </START_ANGLE>\n<STOP_ANGLE>240</STOP_ANGLE>\n</ARC>\n</PD>\n</POS>\n</LIA>\n</ANS>\n\n" }; + var HTTPMessage send_resp := { response := resp }; + var Close c := { client_id := omit }; + + map(self:HTTP_server_port, system:HTTP_server_port); + + HTTP_server_port.send(listen); + + timer T_guard := 500.0; + T_guard.start; + var boolean ready := false; + + while(ready == false) { + alt { + [] HTTP_server_port.receive(recv_req) { + HTTP_server_port.send(send_resp); + } + [] HTTP_server_port.receive(h) { + HTTP_server_port.send(c); + ready := true; + setverdict(pass); + } + [] T_guard.timeout { + setverdict(fail); + } + }; + } + + unmap(self:HTTP_server_port, system:HTTP_server_port); +} + +//==== Encode decode test ==== + +function f_singleEncDecCheck( in HTTPMessage p_msg) +{ + var template HTTPMessage tr_expectedMsg := p_msg; + if(ischosen( p_msg.request ) ){ + tr_expectedMsg.request.client_id := *; + } + else if(ischosen( p_msg.response )){ + tr_expectedMsg.response.client_id := *; + } + + var octetstring vloc_encodedMsg; + log("Original message:",p_msg); + log("\n======================\n"); + vloc_encodedMsg := enc_HTTPMessage(p_msg); + log("Encoded message:",vloc_encodedMsg); + + //==== Request decoding ==== + var HTTPMessage vloc_decodedMsg; + var integer vl_lengthOfRemainingMsg := dec_HTTPMessage( vloc_encodedMsg, vloc_decodedMsg ); //socket debugging has default value + log("length of the encoded msg: ", lengthof(vloc_encodedMsg)); + log("length of the remaining msg after encoding:", vl_lengthOfRemainingMsg); + if( vl_lengthOfRemainingMsg<lengthof(vloc_encodedMsg)) + { + log( "The decoded message:", vloc_decodedMsg); + + if(match( vloc_decodedMsg,tr_expectedMsg)) + { + setverdict(pass); + } + else + { + log(match( vloc_decodedMsg,tr_expectedMsg)); + setverdict(fail); + } + } + else + { + log( "Decoding not happened"); + setverdict(fail); + } +} + +function f_EncDec() runs on MTC +{ + + //=== Request Test ==== + + var HeaderLines hd := { {header_name := "Content-Type", header_value := "text/xml"}, + {header_name := "Content-Length", header_value := "510" }, + {header_name := "Expires", header_value := "Sat, 01 Jan 2000 00:00:00 GMT" }, + {header_name := "Pragma", header_value := "no-cache" } }; + var HTTPRequest r := { client_id := omit, method := "POST", uri := "/", + version_major := 1, version_minor := 0, header := hd, body := "<?xml version='1.0' encoding='ISO-8859-1' standalone='yes'?><!DOCTYPE ANS SYSTEM 'file://mpp50_ans.dtd'><ANS ver=\"5.00\"><PUSH_USER><PUSH_ID>clientPush</PUSH_ID><PUSH_PWD>clientPush</PUSH_PWD></PUSH_USER><LPA><GMT_OFF>+0100</GMT_OFF><POS msid=\"4670112345\"><PD><TIME>20040117132719</TIME><POLYGON><LL_POINT><LAT>N100410</LAT><LONG>E0202020</LONG></LL_POINT><LL_POINT><LAT>N101610</LAT><LONG>E0202620</LONG></LL_POINT><LL_POINT><LAT>N101610</LAT><LONG>E0201420</LONG></LL_POINT></POLYGON></PD></POS></LPA></ANS>xy" }; //xy will be fragmented????? + + var HTTPMessage send_req := { request := r }; + f_singleEncDecCheck( send_req ); + + //==== Response Test ==== + var HTTPResponse resp := { client_id := omit, version_major := 1, version_minor := 1, statuscode := 200, statustext := "OK", + header := { { header_name := "Server", header_value := "TTCN Test Suite simulated HTTP/1.1 server" }, + { header_name := "Content-Length", header_value := "643" } }, + body := "<?xml version= '1.0' encoding='ISO-8859-1' standalone='yes'?>\n<!DOCTYPE ANS>\n<ANS ver=\"3.00\">\n<LIA>\n<GMT_OFF>+0100</GMT_OFF>\n<POS msid=\"1234512345\">\n<PD>\n<TIME>20000626171825</TIME>\n<ARC>\n<LL_POINT>\n<LAT>N301628</LAT>\n<LONG>W974425</LONG>\n</LL_POINT>\n<IN_RAD>1100</IN_RAD>\n<OUT_RAD>1650</OUT_RAD>\n<START_ANGLE>120</START_ANGLE>\n<STOP_ANGLE>240</STOP_ANGLE>\n</ARC>\n</PD>\n</POS>\n<POS msid=\"1234512346\">\n<PD>\n<TIME>20000626171825</TIME>\n<ARC>\n<LL_POINT>\n<LAT>N301630</LAT>\n<LONG>W974450</LONG>\n</LL_POINT>\n<IN_RAD>0</IN_RAD>\n<OUT_RAD>1650</OUT_RAD>\n<START_ANGLE> 120 </START_ANGLE>\n<STOP_ANGLE>240</STOP_ANGLE>\n</ARC>\n</PD>\n</POS>\n</LIA>\n</ANS>\n\n" }; + var HTTPMessage send_resp := { response := resp }; + + f_singleEncDecCheck( send_resp ); + + +}//f_EncDec + + +function f_EncDec2() runs on MTC { + + var CHARSTRINGS test_msgs := { + "HTTP/1.1 302 Moved Temporarily\r\nDate: Wed, 22 Feb 2006 13:37:49 GMT\r\nPragma: no-cache\r\nLocation: http://caylem.etm.ericsson.se:7001/McxOwu/list_useractions.jsp?reload\r\nContent-Type: text/html\r\nExpires: Sat, 6 May 1995 12:00:00 GMT\r\nTransfer-Encoding: chunked\r\nCache-Control: no-store, no-cache, must-revalidate\r\nCache-Control: post-check=0, pre-check=0\r\n\r\n014d\r\n<html><head><title>302 Moved Temporarily</title></head>\r\n<body bgcolor=\"#FFFFFF\">\r\n<p>This document you requested has moved temporarily.</p>\r\n<p>It's now at <a href=\"http://caylem.etm.ericsson.se:7001/McxOwu/list_useractions.jsp?reload\">http://caylem.etm.ericsson.se:7001/McxOwu/list_useractions.jsp?reload</a>.</p>\r\n</body></html>\r\n\r\n0000\r\n\r\n", + "HTTP/1.1 200 OK\r\nDate: Wed, 22 Feb 2006 13:37:49 GMT\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\n\r\n0fe8\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n\r\n<html>\r\n<head>\r\n<title>Presence</title>\r\n\r\n<script>\r\nvar frameset2 = null;\r\nvar frameset1 = null;\r\n\r\nvar winW = 630, winH = 460;\r\n\r\nfunction getWinSize() {\r\n if (parseInt(navigator.appVersion)>3) {\r\n if (navigator.appName==\"Netscape\") {\r\n winW = window.innerWidth;\r\n winH = window.innerHeight;\r\n }\r\n if (navigator.appName.indexOf(\"Microsoft\")!=-1) {\r\n winW = document.body.offsetWidth;\r\n winH = document.body.offsetHeight;\r\n }\r\n }\r\n //alert(\"winW=\" + winW + \" winH=\" + winH);\r\n}\r\nvar currRow = null;\r\nfunction tr_mouseover(row) {\r\n if (!row) {\r\n row = getrow(window.event.srcElement);\r\n if (!row)return;\r\n }\r\n if (row.style.backgroundColor == \"\") {\r\n row.style.backgroundColor = \"lightgrey\";\r\n }\r\n}\r\n\r\nfunction tr_mouseout(row) {\r\n if (!row) {\r\n row = getrow(window.event.srcElement);\r\n if (!row)return;\r\n }\r\n if (row.style.backgroundColor == \"lightgrey\") {\r\n row.style.backgroundColor= \"\";\r\n }\r\n}\r\n\r\nfunction getrow(obj)\r\n{\r\n while(obj && obj.tagName != \"TR\") obj = obj.parentNode;\r\n return obj;\r\n}\r\n// Remove leading and trailing white space\r\nfunction trim(txt) { \r\n //alert(\"trim=\" + txt);\r\n \r\n try {\r\n return txt.replace(/(^ +)|( +$)|(\t)/g,\"\");\r\n } catch (e) {\r\n var x = new String(txt);\r\n //alert(\"x=\" + x);\r\n while (x.charAt(0) == \" \") {\r\n x = x.substring(1);\r\n if (x.length == 0) return \"\";\r\n //alert(\"x=\" + x);\r\n }\r\n if (x.length == 0) return \"\";\r\n while (x.charAt(x.length - 1) == \" \") {\r\n x = x.substring(0, x.length-1);\r\n if (x.length == 0) return \"\";\r\n }\r\n \r\n return x; \r\n \r\n \r\n }\r\n\r\n}\r\n\r\nfunction notyetimplemented()\r\n{\r\n alert(\"not yet implemented\");\r\n}\r\n\r\nfunction logout()\r\n{\r\n top.frames[\"_owu_hidden\"].location.assign(\"hidden_logout.jsp\");\r\n// window.parent.frames[\"_owu_hidden\"].location.assign(\"hidden_logout.jsp\");\r\n}\r\nfunction dorefresh()\r\n{\r\n try {\r\n top.frames[\"_owu_sidebar\"].location = \"PrepareSidebar?noselect\";\r\n } catch (e) {\r\n alert(\"failed to reload frames\" + e.toString());\r\n }\r\n}\r\n\r\nfunction NumberChanged(obj) {\r\n\r\n var val = obj.value;\r\n var leadingplus = false;\r\n if (val.search(/^\\+/) == 0) {\r\n leadingplus = true;\r\n val = val.substring(1);\r\n }\r\n if (val.search(/[^0-9]/) >= 0) { \r\n //alert(\"Give a number\");\r\n val = val.replace(/[^0-9]/g, \"\");\r\n if (leadingplus) {\r\n obj.value = \"+\" + val;\r\n } else {\r\n obj.value = val;\r\n }\r\n }\r\n \r\n}\r\n\r\nvar modalObj, modalFunc, modalWin;\r\nfunction showModal(obj, func, filename, args, args1) {\r\n var retval = \"\";\r\n// if (window.showModalDialog) {\r\n// retval = window.showModalDialog(filename, args, args1);\r\n// } else {\r\n modalObj = obj;\r\n modalFunc = func;\r\n document.getElementById(\"modalArg\").value = args;\r\n args1 = args1.replace(/;/g, \",\");\r\n args1 = args1.replace(/:/g, \"=\");\r\n args1 = args1.replace(/dialogWidth/g, \"width\");\r\n args1 = args1.replace(/dialogHeight/g, \"height\");\r\n args1 = args1.replace(/dialogTop/g, \"top\");\r\n args1 = args1.replace(/dialogLeft/g, \"left\");\r\n args1 = args1.replace(/scroll/g, \"scrollbars\");\r\n \r\n //alert(\"modal:\" + args1 );\r\n //alert(\"window.left=\" + window.screen.left + \" window.top=\" + window.screen.top\r\n // + \"\\window.screeX=\" + window.screenX + \" window.screenY=\" + window.screenY);\r\n\r\n //alert(\"showmodal:\" + args1);\r\n //modalWin = window.open(filename, \" \", args1 );\r\n //filename = \"indexpopup.jsp?\" + filename;\r\n modalWin = window.open(filename, \"_owu_popup\", args1);\r\n modalWin.focus();\r\n \r\n// }\r\n return retval;\r\n}\r\n\r\nfunction modalDone() {\r\n if (modalObj && modalFunc) {\r\n modalFunc(modalObj, document.getElementById(\"modalRetval\").value);\r\n }\r\n}\r\n\r\nfunction goBack() {\r\n if (window.name == \"_owu_list\") {\r\n window.location.assign(\"list_catalog.jsp?catalog=catalogue\");\r\n } else {\r\n window.history.go(-1);\r\n }\r\n}\r\nfunction scroll2View(obj)\r\n{\r\n try {\r\n var parent = obj.parentNode;\r\n while (parent && parent.tagName != (\"DIV\")) parent = parent.parentNode;\r\n" & + // wrapped into max. 8000 columns lines because ClearCase complains about too long lines + " \r\n //alert(\"scroll2view=\" + parent.id);\r\n var totsize = parent.offsetHeight; // this is the visible area \r\n0fe8\r\nsize\r\n var currtop = parent.scrollTop; //here begins the visible area\r\n var beginPos = obj.offsetTop;\r\n var step = obj.offsetHeight + 3;\r\n // alert(\"step=\" + step + \" padding=\" + obj.style.paddingTop);\r\n var endPos = beginPos + step;\r\n \r\n while (endPos > (currtop + totsize)) {\r\n currtop += step;\r\n }\r\n while (beginPos < currtop) {\r\n currtop -= step;\r\n }\r\n parent.scrollTop = currtop;\r\n //window.status = \"scrolltop=\" + currtop;\r\n } catch(e) {\r\n window.status = \"Failed scroll2view\";\r\n }\r\n}\r\n\r\n</script>\r\n\r\n<script>\r\n\r\nfunction init() {\r\n //document.getElementById(\"p_text\").select();\r\n\r\n\r\n var doreload = \"reload\";\r\n if (doreload== \"reload\") {\r\n dorefresh();\r\n }\r\n \r\n var errormsg = \"\";\r\n if (errormsg != \"\") {\r\n errormsg = errormsg.replace(/^error=/i, \"\");\r\n errormsg = errormsg.replace(/\\%20/g, \" \");\r\n alert(errormsg);\r\n }\r\n \r\n}\r\n\r\nfunction removePresence() {\r\n document.getElementById(\"presence_code\").value = \"0\";\r\n document.forms[\"presenceform\"].submit();\r\n}\r\n\r\nfunction pcodeChanged(obj) {\r\n //alert(\"pcodechanged=\" + obj.options[obj.selectedIndex].value);\r\n var pcodes = obj.options[obj.selectedIndex].value;\r\n if (pcodes == \"\") return;\r\n \r\n var tmp = pcodes.split(\"_\");\r\n var pcode = tmp[0];\r\n var number = tmp[1];\r\n \r\n var actionimage = document.getElementById(\"actionimage\");\r\n if (actionimage) {\r\n if (number == \"\") {\r\n actionimage.src=\"img/not_available_no_CFP.gif\";\r\n } else {\r\n actionimage.src=\"img/not_available_CFP.gif\";\r\n }\r\n }\r\n if (number == \"x\") {\r\n document.getElementById(\"diversionnbr\").style.display = \"\";\r\n } else {\r\n document.getElementById(\"diversionnbr\").style.display = \"none\";\r\n }\r\n}\r\nfunction setPresence() {\r\n var pcodelist = document.getElementById(\"pcodelist\");\r\n if (pcodelist.selectedIndex <0 || pcodelist.options[pcodelist.selectedIndex].value == \"\") {\r\n alert(\"do pick a valid option\")\r\n return;\r\n }\r\n var pcodes = pcodelist.options[pcodelist.selectedIndex].value ;\r\n var tmp = pcodes.split(\"_\");\r\n var pcode = tmp[0];\r\n var number = tmp[1];\r\n \r\n document.getElementById(\"presence_code\").value = pcode;\r\n if (number == \"x\") {\r\n number = trim(document.getElementById(\"diversionnbr\").value);\r\n } \r\n document.getElementById(\"presence_divertnbr\").value = number;\r\n \r\n var until = document.getElementById(\"untildate\").value \r\n + \" \" + document.getElementById(\"untiltime\").value;\r\n until = trim(until);\r\n if (until != \"\") {\r\n document.getElementById(\"presence_until\").value = until;\r\n }\r\n \r\n var msgelem = document.getElementById(\"p_text\");\r\n //just make sure that the text is not the initial expl. text.\r\n if (msgelem.onkeydown == null) { \r\n var ptext = trim(msgelem.value);\r\n if (ptext != \"\") {\r\n document.getElementById(\"presence_text\").value = ptext;\r\n }\r\n }\r\n document.forms[\"presenceform\"].submit();\r\n}\r\nfunction presetPresence(idx) {\r\n document.getElementById(\"presence_preset\").value = idx;\r\n document.forms[\"presenceform\"].submit();\r\n \r\n}\r\n\r\nfunction SetDeflect()\r\n{\r\n var elems = document.getElementsByName(\"cf\");\r\n for (var i=0; i <elems.length; i++) {\r\n if (elems[i].checked) {\r\n var deflectnr = elems[i].value;\r\n if (deflectnr == \"X\") {\r\n deflectnr = document.getElementById(\"cf_number\").value;\r\n }\r\n document.getElementById(\"calldeflectnr\").value = deflectnr;\r\n break;\r\n }\r\n }\r\n document.forms[\"calldeflectform\"].submit();\r\n}\r\n\r\nfunction cfClicked(obj) {\r\n //alert(\"obj=\" + obj.checked);\r\n if (obj.checked && obj.value == \"X\") {\r\n document.getElementById(\"cf_number\").style.visibility = \"\";\r\n document.getElementById(\"cf_number\").focus();\r\n } else {\r\n document.getElementById(\"cf_number\").style.visibility = \"hidden\";\r\n }\r\n}\r\n\r\nfunction ActivateGroups()\r\n{\r\n document.forms[\"hgsettng\"].submit();\r\n}\r\n\r\nfunction showmoreoptions() {\r\n document.getElementById(\"moreoptionstable\").style.display = \"\";\r\n document.getElementById(\"moreoptionsbutton\").style.display = \"\";\r\n}\r\nfunction divmsgChanged(obj) {\r\n if (parseInt(obj.value.length) > 255) {\r\n obj.value = obj.value.substring(0,255);\r\n alert(\"Max 255\");\r\n \r\n0fe8\r\n}\r\n //window.status = obj.value.length;\r\n} \r\nfunction resetUserSettings() \r\n{\r\n document.forms[\"resetuserform\"].submit();\r\n}\r\n</script>\r\n<style type=\"text/css\">\r\n\r\nbody {\r\n font-family: verdana, arial;\r\n font-size: 100%;\r\n background-image: url(img/body.gif);\r\n color : black;\r\n}\r\n\r\ntable {\r\n font-family: verdana, arial;\r\n font-size: 90%;\r\n}\r\n\r\n.loginform {\r\n font-size: 90%;\r\n color : black;\r\n}\r\n.button {\r\n font-size:80%;\r\n font-weight:bold;\r\n padding:1;\r\n}\r\n.mainform {\r\n color : black;\r\n background-color:#E0E0E0;\r\n font-size:70%;\r\n width:100%;\r\n height:100%;\r\n padding:0;\r\n margin:0;\r\n\r\n} \r\n.attendantform {\r\n color : black;\r\n background-image: url(img/body.gif);\r\n margin:0;\r\n padding:0;\r\n width:100%;\r\n height:100%;\r\n}\r\n\r\n.maintitle {\r\n font-weight: bold;\r\n color : black;\r\n letter-spacing:1;\r\n height:50px;\r\n width:230px;\r\n padding:0;" & + "\r\n margin:0;\r\n background-image: url(img/top.gif);\r\n}\r\n\r\n.actionmenu {\r\n font-size: 90%;\r\n color : black;\r\n background-color:#E0E0E0;\r\n margin : 5;\r\n padding:5;\r\n width:99%;\r\n\r\n}\r\n.actiondropdown {\r\n color : black;\r\n}\r\n\r\n.searchform {\r\n font-size: 90%;\r\n color : black;\r\n background-image: url(img/body.gif);\r\n}\r\n\r\n/* Used by the sidebar */\r\n#mainbody {\r\n height:99%;\r\n background-color:#E0E0E0; \r\n min-width:130px;\r\n left:5;\r\n top:3;\r\n position:absolute;\r\n \r\n}\r\n\r\n.menutree {\r\n padding:0;\r\n align:center;\r\n color: black;\r\n min-width:230px;\r\n width:100%;\r\n}\r\n\r\n.settingsbody {\r\n padding:0;\r\n align:center;\r\n color: black;\r\n min-width:198px;\r\n width:100%;\r\n background-image: url(img/body.gif);\r\n top:70px;\r\n position:absolute;\r\n font-weight:normal;\r\n height:90%;\r\n font-size:80%;\r\n}\r\n.settingslist {\r\n font-size:80%;\r\n}\r\n.inputfield {\r\n font-size:90%;\r\n}\r\n.settingsheading {\r\n padding:0 0 0 12;\r\n width:30%;\r\n}\r\n.treerow {\r\n font-weight:normal;\r\n font-size:85%;\r\n vertical-align:text-top;\r\n padding:3 0 3 0 ;\r\n margin:0;\r\n color : black;\r\n cursor:hand;\r\n min-height:16px;\r\n}\r\n.rowheading {\r\n background-color:#CCCCCC;\r\n font-weight:bold;\r\n color:black;\r\n border:3 outset lightgray;\r\n margin:2px;\r\n padding-left:5;\r\n cursor:hand;\r\n align:center;\r\n}\r\n\r\n#maincatalogbody {\r\n height:99%;\r\n background-image: url(img/body.gif);\r\n width:100%;\r\n left:5;\r\n top:3;\r\n position:absolute;\r\n}\r\n\r\n.imgbutton {\r\n background-color:#CCCCCC;\r\n font-weight:bold;\r\n color:black;\r\n border:3 outset lightgray;\r\n margin:2px;\r\n padding:2;\r\n cursor:hand;\r\n align:center;\r\n font-size:80%;\r\n}\r\n\r\n.numberbutton {\r\n background-color:#CCCCCC;\r\n font-weight:normal;\r\n color:black;\r\n margin:1px;\r\n cursor:hand;\r\n align:center;\r\n border:3 outset lightgray;\r\n height:20px;;\r\n width:120px;\r\n vertical-align:bottom;\r\n padding : 0 0 0 5;\r\n font-size:80%;\r\n \r\n}\r\n\r\n.numberbuttonpushed {\r\n background-color:#E0E0E0;\r\n font-weight:bold;\r\n /*color:blue;*/\r\n margin:1px;\r\n cursor:hand;\r\n align:center;\r\n border:3 inset lightgray;\r\n height:20px;;\r\n width:120px;\r\n vertical-align:bottom;\r\n padding : 0 0 0 5;\r\n font-size:80%;\r\n \r\n}\r\n.actionsmallbutton {\r\n background-color:#CCCCCC;\r\n font-weight:bold;\r\n color:black;\r\n margin:1px;\r\n cursor:hand;\r\n align:center;\r\n font-size:70%;\r\n border:2 outset lightgray;\r\n height:11px;\r\n width:11px;\r\n vertical-align:bottom;\r\n}\r\n.actionbutton {\r\n background-color:#CCCCCC;\r\n font-weight:bold;\r\n color:black;\r\n margin:2px;\r\n cursor:hand;\r\n align:center;\r\n font-size:60%;\r\n border:5 outset lightgray;\r\n height:25px;\r\n width:25px;\r\n vertical-align:top;\r\n}\r\n\r\n.actionbuttonpushed {\r\n background-color:#E0E0E0;\r\n font-weight:bold;\r\n color:black;\r\n margin:2px;\r\n align:center;\r\n font-size:70%;\r\n border:5 inset lightgray;\r\n height:25px;\r\n width:25px;\r\n vertical-align:top;\r\n cursor:hand;\r\n \r\n}\r\n\r\n\r\n.treecell {\r\n padding:0 0 2 2;\r\n}\r\n.treespacer {\r\n padding:0;\r\n margin:0;\r\n min-height:2px;\r\n font-size:1px;\r\n width:200px;\r\n \r\n}\r\n.popupform {\r\n align : center;\r\n font-size: 90%;\r\n color : black;\r\n background-image: url(img/body.gif);\r\n}\r\n\r\n.popuptitle {\r\n font-size: 120%;\r\n font-weight : bold;\r\n letter-spacing : 1;\r\n}\r\n.popuptab {\r\n font-size: 110%;\r\n letter-spacing : 1;\r\n border-top : 1 solid black;\r\n border-right : 1 solid black;\r\n bor\r\n0438\r\nder-left : 1 solid black;\r\n padding : 4;\r\n margin : 8 3 0 3;\r\n width : 100%;\r\n height:80%;\r\n vertical-align:text-top;\r\n background-color:black;\r\n align:center; \r\n color:black;\r\n cursor:hand;\r\n}\r\n.tabselected {\r\n font-size: 110%;\r\n letter-spacing : 1;\r\n border : 1 solid black;\r\n border-bottom : 0;\r\n padding : 4 4 0 4;\r\n margin : 0;\r\n text-align : left;\r\n vertical-align:text-top;\r\n align:center;\r\n background-color:#E0E0E0;\r\n color:black;\r\n}\r\n\r\n.popupbutton {\r\n width: 100px;\r\n}\r\n\r\n.resultlist {\r\n align:center;\r\n color: black;\r\n width:100%;\r\n height:89%;\r\n overflow:auto;\r\n position:absolute;\r\n background-color:#E0E0E0;\r\n \r\n}\r\n.resultrow {\r\n font-weight:normal;\r\n font-size:75%;\r\n vertical-align:text-top;\r\n padding:1;\r\n margin:0;\r\n color : black;\r\n cursor:hand;\r\n min-height:16px;\r\n}\r\n.resultheading {\r\n background-color:#CCCCCC;\r\n font-weight:bold;\r\n color:black;\r\n border:3 outset lightgray;\r\n margin:2px;\r\n padding-left:5;\r\n cursor:hand;\r\n align:center;\r\n font-size:85%;\r\n}\r\n.actiontextarea {\r\n font-size:90%;\r\n text-align:left;\r\n width:100%;\r\n height:100px;\r\n}\r\n\r\n</style>\r\n0fe8\r\n\r\n\r\n</head>\r\n<body onload=\"init();\" >\r\n\r\n\r\n<div id=\"mainbody\" >\r\n\r\n<form name=\"resetuserform\" target=\"_self\" action=\"servlet/DrsResetUser\" method=\"post\">\r\n<input type=hidden name=\"resetuser_dirid\" id=\"resetuser_dirid\" value=\"3619010001:046182\">\r\n</form>\r\n\r\n<form name=\"presenceform\" target=\"_self\" action=\"DrsPresence\" method=\"post\">\r\n<input type=hidden name=\"presence_code\" id=\"presence_code\" value=\"\">\r\n<input type=hidden name=\"presence_divertnbr\" id=\"presence_divertnbr\" value=\"\">\r\n<input type=hidden name=\"presence_until\" id=\"presence_until\" value=\"\">\r\n<input type=hidden name=\"presence_dirid\" id=\"presence_dirid\" value=\"\">\r\n<input type=hidden name=\"presence_text\" id=\"presence_text\" value=\"\">\r\n<input type=hidden name=\"presence_preset\" id=\"presence_preset\" value=\"\">\r\n</form>\r\n\r\n<div class=\"maintitle\" style=\"width:100%\">\r\n<table cellspacing=0 cellpadding=3 width=\"100%\" >\r\n<tr>\r\n <td class=\"maintitle\" style=\"width:100%\" align=baseline>\r\n <img src=\"img/spacer.gif\" height=50 width=2>\r\n Sambal Bij (1100)\r\n<!-- toolbox -->\r\n <td align=right valign=baseline nowrap> \r\n \r\n <span id=\"resetbutton\" class=\"actionbutton\" onclick=\"resetUserSettings()\" >\r\n <img src=\"img/spacer.gif\" width=\"25\" heigth=\"25\">Reset user settings\r\n </span>\r\n \r\n <span id=\"logoutbutton\" class=\"actionbutton\" onclick=\"logout()\" >\r\n <img src=\"img/spacer.gif\" width=\"25\" heigth=\"25\">Log out\r\n </span>\r\n<tr><td colspan=2><hr>\r\n\r\n</table>\r\n\r\n</div>\r\n\r\n<div class=\"settingsbody\" id=\"presencemenu\">\r\n\r\n<table style=\"width:100%;color:black;background-color:#E0E0E0\" border=0 cellpadding=3 cellspacing=2>\r\n<tr><td style=\"width:35%;border:1 solid gray;\">\r\n\r\n <table style=\"width:100%;color:black;background-color:#E0E0E0\" border=0 cellpadding=3 cellspacing=2>\r\n <tr><td style=\"font-size:100%\"><b>Presence\r\n \r\n\r\n <td nowrap> <img src='img/not_available_no_CFP.gif'>Left for the day\r\n\r\n\r\n <tr>\r\n <td colspan=2><hr>\r\n \r\n\r\n" & + " <tr style=\"display:\"><td colspan=2>Predefined options\r\n \r\n\r\n <tr style=\"display:\">\r\n <td colspan=2 >\r\n <span style=\"width:70%\" class='imgbutton' onclick=\"presetPresence('0');\" >\r\n <img src='img/available.gif' width=16 height=16>Change to Available\r\n </span>\r\n <br>\r\n\r\n <tr style=\"display:\">\r\n <td colspan=2 >\r\n <span style=\"width:70%\" class='imgbutton' onclick=\"presetPresence('1');\" >\r\n <img src='img/not_available_no_CFP.gif' width=16 height=16>Change to Busy\r\n </span>\r\n <br>\r\n\r\n <tr style=\"display:\">\r\n <td colspan=2 >\r\n <span style=\"width:70%\" class='imgbutton' onclick=\"presetPresence('2');\" >\r\n <img src='img/not_available_no_CFP.gif' width=16 height=16>Change to Meeting\r\n </span>\r\n <br>\r\n\r\n <tr style=\"display:\">\r\n <td colspan=2 >\r\n <span style=\"width:70%\" class='imgbutton' onclick=\"presetPresence('3');\" >\r\n <img src='img/not_available_no_CFP.gif' width=16 height=16>Change to Lunch\r\n </span>\r\n <br>\r\n\r\n <tr style=\"display:\">\r\n <td colspan=2 >\r\n <span style=\"width:70%\" class='imgbutton' onclick=\"presetPresence('4');\" >\r\n <img src='img/not_available_no_CFP.gif' width=16 height=16>Change to Left for the day\r\n </span>\r\n <br>\r\n\r\n <tr>\r\n <td colspan=2><br><hr>\r\n \r\n <tr><td ><a href=# onclick=\"showmoreoptions()\" >More options...</a>\r\n \r\n <td style=\"display:none\" id=\"moreoptionsbutton\" nowrap align=right><span class=\"imgbutton\" style=\"font-size:75%\" onclick=\"setPresence();\">\r\n <img id=\"actionimage\" src=\"img/spacer.gif\"> \r\n Change now</span>\r\n \r\n\r\n <tr>\r\n <td colspan=2>\r\n <table id=\"moreoptionstable\" style=\"display:none\">\r\n <tr>\r\n <td colspan=2 valign=top >\r\n <select style=\"width:100%\" id=\"pcodelist\" onchange=\"pcodeChanged(this)\" >\r\n <option value=''>------------------------------------</option>\r\n<option value='1_'>Busy - No diversion\n<option value='1_-1'>Busy - All calls to main number\n<option value='1_-2'>Busy - All calls to voicemail\n<option value='1_x'>Busy - All calls to number\n<option value=''>------------------------------------</option>\n<option value='2_'>Meeting - No diversion\n<option value='2_-1'>Meeting - All calls to\r\n0f53\r\n main number\n<option value='2_-2'>Meeting - All calls to voicemail\n<option value='2_x'>Meeting - All calls to number\n<option value=''>------------------------------------</option>\n<option value='3_'>Lunch - No diversion\n<option value='3_-1'>Lunch - All calls to main number\n<option value='3_-2'>Lunch - All calls to voicemail\n<option value='3_x'>Lunch - All calls to number\n<option value=''>------------------------------------</option>\n<option value='4_'>Left for the day - No diversion\n<option value='4_-1'>Left for the day - All calls to main number\n<option value='4_-2'>Left for the day - All calls to voicemail\n<option value='4_x'>Left for the day - All calls to number\n<option value=''>------------------------------------</option>\n<option value='5_'>Returns - No diversion\n<option value='5_-1'>Returns - All calls to main number\n<option value='5_-2'>Returns - All calls to voicemail\n<option value='5_x'>Returns - All calls to number\n<option value=''>------------------------------------</option>\n\r\n \r\n </select>\r\n <tr><td colspan=2>\r\n <input type=text value=\"\" onkeyup=\"NumberChanged(this)\" style=\"display:none\" id=\"diversionnbr\">\r\n\r\n <tr>\r\n <td style=\"font-size:90%;\" nowrap colspan=2>Back \r\n <span style=\"font-size:75%\">(MM/dd/yyyy)</span>\r\n <input type=text id=\"untildate\" value=\"\" size=\"10\">\r\n <span style=\"font-size:75%\">(HH:mm)</span>\r\n <input type=text id=\"untiltime\" value=\"\" size=\"5\">\r\n <tr>\r\n <td colspan=2 valign=top width=30%><b>Message\r\n \r\n <tr > \r\n <td colspan=2 valign=top >\r\n <textarea style=\"width:99%;\" rows=5 classname=\"actiontextarea\"\r\n id=\"p_text\" onkeydown=\"this.value='';this.onkeydown=null\" onkeyup=\"divmsgChanged(this)\">Here you can write your message to the attendant and others. Max 255 characters.</textarea>\r\n \r\n \r\n </table><!--more options-->\r\n </table>\r\n\r\n<!-- Call deflect -->\r\n<td style=\"width:35%;border:1 solid gray;display:none\" valign=top>\r\n <table style=\"color:black;background-color:#E0E0E0;width:100%\" border=0 cellpadding=3 cellspacing=2>\r\n <tr><td style=\"font-size:100%\"><b>Deflect call\r\n <td align=right><input class=\"imgbutton\" style=\"font-size:80%;\" \r\n type=\"button\" value=\"Change\" onclick=\"SetDeflect()\" >\r\n \r\n <tr><td colspan=2><hr> \r\n <tr onmouseover=\"tr_mouseover(this);\" onmouseout=\"tr_mouseout(this)\" class=treerow>\r\n <td colspan=2><input onclick=\"cfClicked(this);\" type=radio id=\"cf_operator\" name=\"cf\" value=\"-1\" > Main number\r\n <tr onmouseover=\"tr_mouseover(this);\" onmouseout=\"tr_mouseout(this)\" class=treerow>\r\n <td colspan=2><input onclick=\"cfClicked(this);\" type=radio id=\"cf_voicemail\" name=\"cf\" value=\"-2\" > Voicemail\r\n <tr onmouseover=\"tr_mouseover(this);\" onmouseout=\"tr_mouseout(this)\" class=treerow>\r\n <td colspan=2><input onclick=\"cfClicked(this);\" type=radio id=\"cf_x\" name=\"cf\" value=\"X\" > Phone\r\n <input type=text name=\"cf_number\" id=\"cf_number\" onkeyup=\"NumberChanged(this);\" style=\"visibility:hidden\" value=\"\">\r\n \r\n </table>\r\n\r\n\r\n<form name=\"calldeflectform\" target=\"_self\" action=\"servlet/DrsDeflect\" method=\"post\">\r\n<input type=hidden name=\"dirid\" id=\"dirid\" value=\"\">\r\n<input type=hidden name=\"calldeflectnr\" id=\"calldeflectnr\" value=\"\">\r\n</form>\r\n\r\n<!-- CDG/huntgroups -->\r\n<td style=\"width:35%;border:1 solid gray;\" valign=top>\r\n <form name=\"hgsettng\" target=\"_self\" action=\"servlet/DrsHuntGroup\" method=\"post\">\r\n <input type=hidden name=\"dirid\" id=\"dirid\" value=\"\">\r\n <table style=\"color:black;background-color:#E0E0E0;width:100%\" border=0 cellpadding=3 cellspacing=2>\r\n <tr><td style=\"font-size:100%;\"><b>Activate/deactivate <br>Call distribution groups\r\n <td align=right valign=top><input class=\"imgbutton\" style=\"font-size:80%;\" \r\n type=\"button\" value=\"Change\" onclick=\"ActivateGroups()\" >\r\n <tr><td colspan=2><hr> \r\n<tr><td>Not member of any call distribution group\n\r\n </form>\r\n </table>\r\n\r\n</table>\r\n</div>\r\n</div>\r\n\r\n</body>\r\n</html>\r\n\r\n0000\r\n\r\n" + }; + + var HTTPResponse resp := { client_id := omit, version_major := 1, version_minor := 1, statuscode := 200, statustext := "OK", + header := { { header_name := "Server", header_value := "TTCN Test Suite simulated HTTP/1.1 server" }, + { header_name := "Content-Length", header_value := int2str(lengthof(test_msgs[0])+ lengthof(test_msgs[1])) } }, + body := test_msgs[0] & test_msgs[1] }; + var HTTPMessage send_resp := { response := resp }; + + f_singleEncDecCheck( send_resp ); + + var octetstring received_reply := '485454502F312E3120333032204D6F7665642054656D706F726172696C790D0A446174653A205765642C2032322046656220323030362031333A33373A343920474D540D0A507261676D613A206E6F2D63616368650D0A4C6F636174696F6E3A20687474703A2F2F6361796C656D2E65746D2E6572696373736F6E2E73653A373030312F4D63784F77752F6C6973745F75736572616374696F6E732E6A73703F72656C6F61640D0A436F6E74656E742D547970653A20746578742F68746D6C0D0A457870697265733A205361742C2036204D617920313939352031323A30303A303020474D540D0A5472616E736665722D456E636F64696E673A206368756E6B65640D0A43616368652D436F6E74726F6C3A206E6F2D73746F72652C206E6F2D63616368652C206D7573742D726576616C69646174650D0A43616368652D436F6E74726F6C3A20706F73742D636865636B3D302C207072652D636865636B3D300D0A0D0A3C68746D6C3E3C686561643E3C7469746C653E333032204D6F7665642054656D706F726172696C793C2F7469746C653E3C2F686561643E0D0A3C626F6479206267636F6C6F723D2223464646464646223E0D0A3C703E5468697320646F63756D656E7420796F752072657175657374656420686173206D6F7665642074656D706F726172696C792E3C2F703E0D0A3C703E49742773206E6F77206174203C6120687265663D22687474703A2F2F6361796C656D2E65746D2E6572696373736F6E2E73653A373030312F4D63784F77752F6C6973745F75736572616374696F6E732E6A73703F72656C6F6164223E687474703A2F2F6361796C656D2E65746D2E6572696373736F6E2E73653A373030312F4D63784F77752F6C6973745F75736572616374696F6E732E6A73703F72656C6F61643C2F613E2E3C2F703E0D0A3C2F626F64793E3C2F68746D6C3E0D0A485454502F312E3120323030204F4B0D0A446174653A205765642C2032322046656220323030362031333A33373A343920474D540D0A436F6E74656E742D547970653A20746578742F68746D6C0D0A5472616E736665722D456E636F64696E673A206368756E6B65640D0A0D0A0D0A0D0A0D0A0D0A0D0A0D0A0D0A0D0A0D0A3C21444F43545950452048544D4C205055424C494320222D2F2F5733432F2F4454442048544D4C20342E3031205472616E736974696F6E616C2F2F454E223E0D0A0D0A3C68746D6C3E0D0A3C686561643E0D0A3C7469746C653E50726573656E63653C2F7469746C653E0D0A0D0A3C7363726970743E0D0A766172206672616D6573657432203D206E756C6C3B0D0A766172206672616D6573657431203D206E756C6C3B0D0A0D0A7661722077696E57203D203633302C2077696E48203D203436303B0D0A0D0A66756E6374696F6E2067657457696E53697A652829207B0D0A09696620287061727365496E74286E6176696761746F722E61707056657273696F6E293E3329207B0D0A0920696620286E6176696761746F722E6170704E616D653D3D224E657473636170652229207B0D0A09202077696E57203D2077696E646F772E696E6E657257696474683B0D0A09202077696E48203D2077696E646F772E696E6E65724865696768743B0D0A09207D0D0A0920696620286E6176696761746F722E6170704E616D652E696E6465784F6628224D6963726F736F66742229213D2D3129207B0D0A09202077696E57203D20646F63756D656E742E626F64792E6F666673657457696474683B0D0A09202077696E48203D20646F63756D656E742E626F64792E6F66667365744865696768743B0D0A09207D0D0A097D0D0A092F2F616C657274282277696E573D22202B2077696E57202B20222077696E483D22202B2077696E48293B0D0A7D0D0A7661722063757272526F77203D206E756C6C3B0D0A66756E6374696F6E2074725F6D6F7573656F76657228726F7729207B0D0A096966202821726F7729207B0D0A0909726F77203D20676574726F772877696E646F772E6576656E742E737263456C656D656E74293B0D0A09096966202821726F772972657475726E3B0D0A097D0D0A0969662028726F772E7374796C652E6261636B67726F756E64436F6C6F72203D3D20222229207B0D0A0909726F772E7374796C652E6261636B67726F756E64436F6C6F72203D20226C6967687467726579223B0D0A097D0D0A7D0D0A0D0A66756E6374696F6E2074725F6D6F7573656F757428726F7729207B0D0A096966202821726F7729207B0D0A0909726F77203D20676574726F772877696E646F772E6576656E742E737263456C656D656E74293B0D0A09096966202821726F772972657475726E3B0D0A097D0D0A0969662028726F772E7374796C652E6261636B67726F756E64436F6C6F72203D3D20226C69676874677265792229207B0D0A0909726F772E7374796C652E6261636B67726F756E64436F6C6F723D2022223B0D0A097D0D0A7D0D0A0D0A66756E6374696F6E20676574726F77286F626A290D0A7B0D0A097768696C65286F626A202626206F626A2E7461674E616D6520213D202254522229206F626A203D206F626A2E706172656E744E6F64653B0D0A0972657475726E206F626A3B0D0A7D0D0A2F2F2052656D6F7665206C656164696E6720616E6420747261696C696E672077686974652073706163650D0A66756E6374696F6E207472696D2874787429207B090D0A092F2F616C65727428227472696D3D22202B20747874293B0D0A090D0A09747279207B0D0A090972657475726E207478742E7265706C616365282F285E202B297C28202B24297C2809292F672C2222293B0D0A097D20636174636820286529207B0D0A09097661722078203D206E657720537472696E6728747874293B0D0A0909092F2F616C6572742822783D22202B2078293B0D0A09097768696C652028782E636861724174283029203D3D2022202229207B0D0A09090978203D20782E737562737472696E672831293B0D0A09090969662028782E6C656E677468203D3D2030292072657475726E2022223B0D0A0909092F2F616C6572742822783D22202B2078293B0D0A09097D0D0A090969662028782E6C656E677468203D3D2030292072657475726E2022223B0D0A09097768696C652028782E63686172417428782E6C656E677468202D203129203D3D2022202229207B0D0A09090978203D20782E737562737472696E6728302C20782E6C656E6774682D31293B0D0A09090969662028782E6C656E677468203D3D2030292072657475726E2022223B0D0A09097D0D0A090D0A090972657475726E20783B090D0A09090D0A090D0A097D0D0A0D0A7D0D0A0D0A66756E6374696F6E206E6F74796574696D706C656D656E74656428290D0A7B0D0A09616C65727428226E6F742079657420696D706C656D656E74656422293B0D0A7D0D0A0D0A66756E6374696F6E206C6F676F757428290D0A7B0D0A09746F702E6672616D65735B225F6F77755F68696464656E225D2E6C6F636174696F6E2E61737369676E282268696464656E5F6C6F676F75742E6A737022293B0D0A2F2F0977696E646F772E706172656E742E6672616D65735B225F6F77755F68696464656E225D2E6C6F636174696F6E2E61737369676E282268696464656E5F6C6F676F75742E6A737022293B0D0A7D0D0A66756E6374696F6E20646F7265667265736828290D0A7B0D0A09747279207B0D0A0909746F702E6672616D65735B225F6F77755F73696465626172225D2E6C6F636174696F6E203D202250726570617265536964656261723F6E6F73656C656374223B0D0A097D20636174636820286529207B0D0A0909616C65727428226661696C656420746F2072656C6F6164206672616D657322202B20652E746F537472696E672829293B0D0A097D0D0A7D0D0A0D0A66756E6374696F6E204E756D6265724368616E676564286F626A29207B0D0A0D0A097661722076616C203D206F626A2E76616C75653B0D0A09766172206C656164696E67706C7573203D2066616C73653B0D0A096966202876616C2E736561726368282F5E5C2B2F29203D3D203029207B0D0A09096C656164696E67706C7573203D20747275653B0D0A090976616C20203D2076616C2E737562737472696E672831293B0D0A097D0D0A096966202876616C2E736561726368282F5B5E302D395D2F29203E3D203029207B200D0A09092F2F616C6572742822476976652061206E756D62657222293B0D0A090976616C203D2076616C2E7265706C616365282F5B5E302D395D2F672C202222293B0D0A0909696620286C656164696E67706C757329207B0D0A0909096F626A2E76616C7565203D20222B22202B2076616C3B0D0A09097D20656C7365207B0D0A0909096F626A2E76616C7565203D2076616C3B0D0A09097D0D0A097D0D0A090D0A7D0D0A0D0A766172206D6F64616C4F626A2C206D6F64616C46756E632C206D6F64616C57696E3B0D0A66756E6374696F6E2073686F774D6F64616C286F626A2C2066756E632C2066696C656E616D652C20617267732C20617267733129207B0D0A097661722072657476616C203D2022223B0D0A2F2F096966202877696E646F772E73686F774D6F64616C4469616C6F6729207B0D0A2F2F090972657476616C203D2077696E646F772E73686F774D6F64616C4469616C6F672866696C656E616D652C20617267732C206172677331293B0D0A2F2F097D20656C7365207B0D0A09096D6F64616C4F626A203D206F626A3B0D0A09096D6F64616C46756E63203D2066756E633B0D0A0909646F63756D656E742E676574456C656D656E744279496428226D6F64616C41726722292E76616C7565203D20617267733B0D0A09096172677331203D2061726773312E7265706C616365282F3B2F672C20222C22293B0D0A09096172677331203D2061726773312E7265706C616365282F3A2F672C20223D22293B0D0A09096172677331203D2061726773312E7265706C616365282F6469616C6F6757696474682F672C2022776964746822293B0D0A09096172677331203D2061726773312E7265706C616365282F6469616C6F674865696768742F672C202268656967687422293B0D0A09096172677331203D2061726773312E7265706C616365282F6469616C6F67546F702F672C2022746F7022293B0D0A09096172677331203D2061726773312E7265706C616365282F6469616C'O & + '6F674C6566742F672C20226C65667422293B0D0A09096172677331203D2061726773312E7265706C616365282F7363726F6C6C2F672C20227363726F6C6C6261727322293B0D0A09090D0A09092F2F616C65727428226D6F64616C3A22202B20617267733120293B0D0A09092F2F616C657274282277696E646F772E6C6566743D22202B2077696E646F772E73637265656E2E6C656674202B20222077696E646F772E746F703D22202B2077696E646F772E73637265656E2E746F700D0A09092F2F092B20225C77696E646F772E7363726565583D22202B2077696E646F772E73637265656E58202B20222077696E646F772E73637265656E593D22202B2077696E646F772E73637265656E59293B0D0A0D0A09092F2F616C657274282273686F776D6F64616C3A22202B206172677331293B0D0A09202020092F2F6D6F64616C57696E203D2077696E646F772E6F70656E2866696C656E616D652C202220222C20617267733120293B0D0A09202020092F2F66696C656E616D65203D2022696E646578706F7075702E6A73703F22202B2066696C656E616D653B0D0A09096D6F64616C57696E203D2077696E646F772E6F70656E2866696C656E616D652C20225F6F77755F706F707570222C206172677331293B0D0A09096D6F64616C57696E2E666F63757328293B0D0A09090D0A2F2F097D0D0A0972657475726E2072657476616C3B0D0A7D0D0A0D0A66756E6374696F6E206D6F64616C446F6E652829207B0D0A09696620286D6F64616C4F626A202626206D6F64616C46756E6329207B0D0A09096D6F64616C46756E63286D6F64616C4F626A2C2020646F63756D656E742E676574456C656D656E744279496428226D6F64616C52657476616C22292E76616C7565293B0D0A097D0D0A7D0D0A0D0A66756E6374696F6E20676F4261636B2829207B0D0A096966202877696E646F772E6E616D65203D3D20225F6F77755F6C6973742229207B0D0A090977696E646F772E6C6F636174696F6E2E61737369676E28226C6973745F636174616C6F672E6A73703F636174616C6F673D636174616C6F67756522293B0D0A097D20656C7365207B0D0A090977696E646F772E686973746F72792E676F282D31293B0D0A097D0D0A7D0D0A66756E6374696F6E207363726F6C6C3256696577286F626A290D0A7B0D0A202020747279207B0D0A2020202076617220706172656E74203D206F626A2E706172656E744E6F64653B0D0A202020207768696C652028706172656E7420262620706172656E742E7461674E616D6520213D20282244495622292920706172656E74203D20706172656E742E706172656E744E6F64653B0D0A2020200D0A202020202F2F616C65727428227363726F6C6C32766965773D22202B20706172656E742E6964293B0D0A2020202076617220746F7473697A6520203D20706172656E742E6F66667365744865696768743B20202F2F2074686973206973207468652076697369626C652061726561200D73697A650D0A202020207661722063757272746F70203D20706172656E742E7363726F6C6C546F703B2020202020202F2F6865726520626567696E73207468652076697369626C6520617265610D0A2020202076617220626567696E506F73203D206F626A2E6F6666736574546F703B0D0A202020207661722073746570203D206F626A2E6F6666736574486569676874202B20333B0D0A2020202F2F09616C6572742822737465703D22202B2073746570202B20222070616464696E673D22202B206F626A2E7374796C652E70616464696E67546F70293B0D0A2020202076617220656E64506F73203D20626567696E506F73202B20737465703B0D0A202020200D0A202020207768696C652028656E64506F73203E202863757272746F70202B20746F7473697A65292920207B0D0A2020202020202063757272746F70202B3D20737465703B0D0A202020207D0D0A202020207768696C652028626567696E506F73203C2063757272746F7029207B0D0A2020202020202063757272746F70202D3D20737465703B0D0A202020207D0D0A20202020706172656E742E7363726F6C6C546F70203D2063757272746F703B0D0A202020202F2F77696E646F772E737461747573203D20227363726F6C6C746F703D22202B2063757272746F703B0D0A2020207D206361746368286529207B0D0A20202020202077696E646F772E737461747573203D20224661696C656420207363726F6C6C3276696577223B0D0A2020207D0D0A7D0D0A0D0A3C2F7363726970743E0D0A0D0A3C7363726970743E0D0A0D0A66756E6374696F6E20696E69742829207B0D0A092F2F646F63756D656E742E676574456C656D656E74427949642822705F7465787422292E73656C65637428293B0D0A0D0A0D0A090976617220646F72656C6F6164203D202272656C6F6164223B0D0A090969662028646F72656C6F61643D3D202272656C6F61642229207B0D0A090909646F7265667265736828293B0D0A09097D0D0A09090D0A0909766172206572726F726D7367203D2022223B0D0A0909696620286572726F726D736720213D20222229207B0D0A0909096572726F726D7367203D206572726F726D73672E7265706C616365282F5E6572726F723D2F692C202222293B0D0A0909096572726F726D7367203D206572726F726D73672E7265706C616365282F5C2532302F672C20222022293B0D0A090909616C657274286572726F726D7367293B0D0A09097D0D0A090D0A7D0D0A0D0A66756E6374696F6E2072656D6F766550726573656E63652829207B0D0A09646F63756D656E742E676574456C656D656E7442794964282270726573656E63655F636F646522292E76616C7565203D202230223B0D0A09646F63756D656E742E666F726D735B2270726573656E6365666F726D225D2E7375626D697428293B0D0A7D0D0A0D0A66756E6374696F6E2070636F64654368616E676564286F626A29207B0D0A092F2F616C657274282270636F64656368616E6765643D22202B206F626A2E6F7074696F6E735B6F626A2E73656C6563746564496E6465785D2E76616C7565293B0D0A097661722070636F646573203D206F626A2E6F7074696F6E735B6F626A2E73656C6563746564496E6465785D2E76616C75653B0D0A096966202870636F646573203D3D202222292072657475726E3B0D0A090D0A0976617220746D70203D2070636F6465732E73706C697428225F22293B0D0A097661722070636F6465203D20746D705B305D3B0D0A09766172206E756D626572203D20746D705B315D3B0D0A090D0A0976617220616374696F6E696D616765203D20646F63756D656E742E676574456C656D656E74427949642822616374696F6E696D61676522293B0D0A0969662028616374696F6E696D61676529207B0D0A0909696620286E756D626572203D3D20222229207B0D0A090909616374696F6E696D6167652E7372633D22696D672F6E6F745F617661696C61626C655F6E6F5F4346502E676966223B0D0A09097D20656C7365207B0D0A090909616374696F6E696D6167652E7372633D22696D672F6E6F745F617661696C61626C655F4346502E676966223B0D0A09097D0D0A097D0D0A09696620286E756D626572203D3D2022782229207B0D0A0909646F63756D656E742E676574456C656D656E74427949642822646976657273696F6E6E627222292E7374796C652E646973706C6179203D2022223B0D0A097D20656C7365207B0D0A0909646F63756D656E742E676574456C656D656E74427949642822646976657273696F6E6E627222292E7374796C652E646973706C6179203D20226E6F6E65223B0D0A097D0D0A7D0D0A66756E6374696F6E2073657450726573656E63652829207B0D0A097661722070636F64656C697374203D20646F63756D656E742E676574456C656D656E7442794964282270636F64656C69737422293B0D0A096966202870636F64656C6973742E73656C6563746564496E646578203C30207C7C2070636F64656C6973742E6F7074696F6E735B70636F64656C6973742E73656C6563746564496E6465785D2E76616C7565203D3D20222229207B0D0A0909616C6572742822646F207069636B20612076616C6964206F7074696F6E22290D0A090972657475726E3B0D0A097D0D0A097661722070636F646573203D2070636F64656C6973742E6F7074696F6E735B70636F64656C6973742E73656C6563746564496E6465785D2E76616C7565203B0D0A0976617220746D70203D2070636F6465732E73706C697428225F22293B0D0A097661722070636F6465203D20746D705B305D3B0D0A09766172206E756D626572203D20746D705B315D3B0D0A090D0A09646F63756D656E742E676574456C656D656E7442794964282270726573656E63655F636F646522292E76616C7565203D2070636F64653B0D0A09696620286E756D626572203D3D2022782229207B0D0A09096E756D626572203D207472696D28646F63756D656E742E676574456C656D656E74427949642822646976657273696F6E6E627222292E76616C7565293B0D0A097D200D0A09646F63756D656E742E676574456C656D656E7442794964282270726573656E63655F6469766572746E627222292E76616C7565203D206E756D6265723B0D0A090D0A0976617220756E74696C203D20646F63756D656E742E676574456C656D656E74427949642822756E74696C6461746522292E76616C7565200D0A090909092B20222022202B20646F63756D656E742E676574456C656D656E74427949642822756E74696C74696D6522292E76616C75653B0D0A09756E74696C203D207472696D28756E74696C293B0D0A0969662028756E74696C20213D20222229207B0D0A0909646F63756D656E742E676574456C656D656E7442794964282270726573656E63655F756E74696C22292E76616C7565203D20756E74696C3B0D0A097D0D0A090D0A09766172206D7367656C656D20203D20646F63756D656E742E676574456C656D656E74427949642822705F7465787422293B0D0A092F2F6A757374206D616B6520737572652074686174207468652074657874206973206E6F742074686520696E697469616C206578706C2E20746578742E0D0A09696620286D7367656C656D2E6F6E6B6579646F776E203D3D206E756C6C29207B200D0A0909766172207074657874203D207472696D286D7367656C656D2E76616C7565293B0D0A090969662028707465787420213D20222229207B0D0A090909646F63756D656E742E676574456C656D656E7442794964282270726573656E63655F7465787422292E76616C7565203D2070746578743B0D0A09097D0D0A097D0D0A09646F63756D656E742E666F726D735B2270726573656E6365666F726D225D2E7375626D697428293B0D0A7D0D0A66756E6374696F6E2070726573657450726573656E6365'O & + '2869647829207B0D0A09646F63756D656E742E676574456C656D656E7442794964282270726573656E63655F70726573657422292E76616C7565203D206964783B0D0A09646F63756D656E742E666F726D735B2270726573656E6365666F726D225D2E7375626D697428293B0D0A090D0A7D0D0A0D0A66756E6374696F6E205365744465666C65637428290D0A7B0D0A0976617220656C656D73203D20646F63756D656E742E676574456C656D656E747342794E616D652822636622293B0D0A09666F72202876617220693D303B2069203C656C656D732E6C656E6774683B20692B2B29207B0D0A090969662028656C656D735B695D2E636865636B656429207B0D0A090909766172206465666C6563746E72203D20656C656D735B695D2E76616C75653B0D0A090909696620286465666C6563746E72203D3D2022582229207B0D0A090909096465666C6563746E72203D20646F63756D656E742E676574456C656D656E7442794964282263665F6E756D62657222292E76616C75653B0D0A0909097D0D0A090909646F63756D656E742E676574456C656D656E7442794964282263616C6C6465666C6563746E7222292E76616C7565203D206465666C6563746E723B0D0A090909627265616B3B0D0A09097D0D0A097D0D0A09646F63756D656E742E666F726D735B2263616C6C6465666C656374666F726D225D2E7375626D697428293B0D0A7D0D0A0D0A66756E6374696F6E206366436C69636B6564286F626A29207B0D0A092F2F616C65727428226F626A3D22202B206F626A2E636865636B6564293B0D0A09696620286F626A2E636865636B6564202626206F626A2E76616C7565203D3D2022582229207B0D0A0909646F63756D656E742E676574456C656D656E7442794964282263665F6E756D62657222292E7374796C652E7669736962696C697479203D2022223B0D0A0909646F63756D656E742E676574456C656D656E7442794964282263665F6E756D62657222292E666F63757328293B0D0A097D20656C7365207B0D0A0909646F63756D656E742E676574456C656D656E7442794964282263665F6E756D62657222292E7374796C652E7669736962696C697479203D202268696464656E223B0D0A097D0D0A7D0D0A0D0A66756E6374696F6E20416374697661746547726F75707328290D0A7B0D0A09646F63756D656E742E666F726D735B226867736574746E67225D2E7375626D697428293B0D0A7D0D0A0D0A66756E6374696F6E2073686F776D6F72656F7074696F6E732829207B0D0A09646F63756D656E742E676574456C656D656E744279496428226D6F72656F7074696F6E737461626C6522292E7374796C652E646973706C6179203D2022223B0D0A09646F63756D656E742E676574456C656D656E744279496428226D6F72656F7074696F6E73627574746F6E22292E7374796C652E646973706C6179203D2022223B0D0A7D0D0A66756E6374696F6E206469766D73674368616E676564286F626A29207B0D0A09696620287061727365496E74286F626A2E76616C75652E6C656E67746829203E2032353529207B0D0A09096F626A2E76616C7565203D206F626A2E76616C75652E737562737472696E6728302C323535293B0D0A0909616C65727428224D61782032353522293B0D0A097D0D0A092F2F77696E646F772E737461747573203D206F626A2E76616C75652E6C656E6774683B0D0A7D090D0A66756E6374696F6E2072657365745573657253657474696E67732829200D0A7B0D0A09646F63756D656E742E666F726D735B22726573657475736572666F726D225D2E7375626D697428293B0D0A7D0D0A3C2F7363726970743E0D0A3C7374796C6520747970653D22746578742F637373223E0D0A0D0A626F6479207B0D0A09666F6E742D66616D696C793A2076657264616E612C20617269616C3B0D0A09666F6E742D73697A653A20313030253B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F626F64792E676966293B0D0A09636F6C6F72203A20626C61636B3B0D0A7D0D0A0D0A7461626C65207B0D0A09666F6E742D66616D696C793A2076657264616E612C20617269616C3B0D0A09666F6E742D73697A653A203930253B0D0A7D0D0A0D0A2E6C6F67696E666F726D207B0D0A09666F6E742D73697A653A203930253B0D0A09636F6C6F72203A20626C61636B3B0D0A7D0D0A2E627574746F6E207B0D0A09666F6E742D73697A653A3830253B0D0A09666F6E742D7765696768743A626F6C643B0D0A0970616464696E673A313B0D0A7D0D0A2E6D61696E666F726D207B0D0A09636F6C6F72203A20626C61636B3B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B0D0A09666F6E742D73697A653A3730253B0D0A0977696474683A313030253B0D0A096865696768743A313030253B0D0A0970616464696E673A303B0D0A096D617267696E3A303B0D0A0D0A7D090D0A2E617474656E64616E74666F726D207B0D0A09636F6C6F72203A20626C61636B3B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F626F64792E676966293B0D0A096D617267696E3A303B0D0A0970616464696E673A303B0D0A0977696474683A313030253B0D0A096865696768743A313030253B0D0A7D0D0A0D0A2E6D61696E7469746C65207B0D0A09666F6E742D7765696768743A20626F6C643B0D0A09636F6C6F72203A20626C61636B3B0D0A096C65747465722D73706163696E673A313B0D0A096865696768743A353070783B0D0A0977696474683A32333070783B0D0A0970616464696E673A303B0D0A096D617267696E3A303B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F746F702E676966293B0D0A7D0D0A0D0A2E616374696F6E6D656E75207B0D0A09666F6E742D73697A653A203930253B0D0A09636F6C6F72203A20626C61636B3B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B0D0A096D617267696E203A20353B0D0A0970616464696E673A353B0D0A0977696474683A3939253B0D0A0D0A7D0D0A2E616374696F6E64726F70646F776E207B0D0A09636F6C6F72203A20626C61636B3B0D0A7D0D0A0D0A2E736561726368666F726D207B0D0A09666F6E742D73697A653A203930253B0D0A09636F6C6F72203A20626C61636B3B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F626F64792E676966293B0D0A7D0D0A0D0A2F2A2055736564206279207468652073696465626172202A2F0D0A236D61696E626F6479207B0D0A096865696768743A3939253B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B200D0A096D696E2D77696474683A31333070783B0D0A096C6566743A353B0D0A09746F703A333B0D0A09706F736974696F6E3A6162736F6C7574653B0D0A090D0A7D0D0A0D0A2E6D656E7574726565207B0D0A0970616464696E673A303B0D0A09616C69676E3A63656E7465723B0D0A09636F6C6F723A20626C61636B3B0D0A096D696E2D77696474683A32333070783B0D0A0977696474683A313030253B0D0A7D0D0A0D0A2E73657474696E6773626F6479207B0D0A0970616464696E673A303B0D0A09616C69676E3A63656E7465723B0D0A09636F6C6F723A20626C61636B3B0D0A096D696E2D77696474683A31393870783B0D0A0977696474683A313030253B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F626F64792E676966293B0D0A09746F703A373070783B0D0A09706F736974696F6E3A6162736F6C7574653B0D0A09666F6E742D7765696768743A6E6F726D616C3B0D0A096865696768743A3930253B0D0A09666F6E742D73697A653A3830253B0D0A7D0D0A2E73657474696E67736C697374207B0D0A09666F6E742D73697A653A3830253B0D0A7D0D0A2E696E7075746669656C64207B0D0A09666F6E742D73697A653A3930253B0D0A7D0D0A2E73657474696E677368656164696E67207B0D0A0970616464696E673A30203020302031323B0D0A0977696474683A3330253B0D0A7D0D0A2E74726565726F77207B0D0A09666F6E742D7765696768743A6E6F726D616C3B0D0A09666F6E742D73697A653A3835253B0D0A09766572746963616C2D616C69676E3A746578742D746F703B0D0A0970616464696E673A33203020332030203B0D0A096D617267696E3A303B0D0A09636F6C6F72203A20626C61636B3B0D0A09637572736F723A68616E643B0D0A096D696E2D6865696768743A313670783B0D0A7D0D0A2E726F7768656164696E67207B0D0A096261636B67726F756E642D636F6C6F723A234343434343433B0D0A09666F6E742D7765696768743A626F6C643B0D0A09636F6C6F723A626C61636B3B0D0A09626F726465723A33206F7574736574206C69676874677261793B0D0A096D617267696E3A3270783B0D0A0970616464696E672D6C6566743A353B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A7D0D0A0D0A236D61696E636174616C6F67626F6479207B0D0A096865696768743A3939253B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F626F64792E676966293B0D0A0977696474683A313030253B0D0A096C6566743A353B0D0A09746F703A333B0D0A09706F736974696F6E3A6162736F6C7574653B0D0A7D0D0A0D0A2E696D67627574746F6E207B0D0A096261636B67726F756E642D636F6C6F723A234343434343433B0D0A09666F6E742D7765696768743A626F6C643B0D0A09636F6C6F723A626C61636B3B0D0A09626F726465723A33206F7574736574206C69676874677261793B0D0A096D617267696E3A3270783B0D0A0970616464696E673A323B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A09666F6E742D73697A653A3830253B0D0A7D0D0A0D0A2E6E756D626572627574746F6E207B0D0A096261636B67726F756E642D636F6C6F723A234343434343433B0D0A09666F6E742D7765696768743A6E6F726D616C3B0D0A09636F6C6F723A626C61636B3B0D0A096D617267696E3A3170783B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A09626F726465723A33206F7574736574206C69676874677261793B0D0A096865696768743A323070783B3B0D0A0977696474683A31323070783B0D0A09766572746963616C2D616C69676E3A626F74746F6D3B0D0A0970616464696E67203A20302030203020353B0D0A09666F6E742D73697A653A3830253B0D0A090D0A7D0D0A0D0A2E6E756D626572627574746F6E707573686564207B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B0D0A09666F6E742D7765696768743A626F6C643B0D0A092F2A636F6C6F'O & + '723A626C75653B2A2F0D0A096D617267696E3A3170783B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A09626F726465723A3320696E736574206C69676874677261793B0D0A096865696768743A323070783B3B0D0A0977696474683A31323070783B0D0A09766572746963616C2D616C69676E3A626F74746F6D3B0D0A0970616464696E67203A20302030203020353B0D0A09666F6E742D73697A653A3830253B0D0A090D0A7D0D0A2E616374696F6E736D616C6C627574746F6E207B0D0A096261636B67726F756E642D636F6C6F723A234343434343433B0D0A09666F6E742D7765696768743A626F6C643B0D0A09636F6C6F723A626C61636B3B0D0A096D617267696E3A3170783B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A09666F6E742D73697A653A3730253B0D0A09626F726465723A32206F7574736574206C69676874677261793B0D0A096865696768743A313170783B0D0A0977696474683A313170783B0D0A09766572746963616C2D616C69676E3A626F74746F6D3B0D0A7D0D0A2E616374696F6E627574746F6E207B0D0A096261636B67726F756E642D636F6C6F723A234343434343433B0D0A09666F6E742D7765696768743A626F6C643B0D0A09636F6C6F723A626C61636B3B0D0A096D617267696E3A3270783B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A09666F6E742D73697A653A3630253B0D0A09626F726465723A35206F7574736574206C69676874677261793B0D0A096865696768743A323570783B0D0A0977696474683A323570783B0D0A09766572746963616C2D616C69676E3A746F703B0D0A7D0D0A0D0A2E616374696F6E627574746F6E707573686564207B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B0D0A09666F6E742D7765696768743A626F6C643B0D0A09636F6C6F723A626C61636B3B0D0A096D617267696E3A3270783B0D0A09616C69676E3A63656E7465723B0D0A09666F6E742D73697A653A3730253B0D0A09626F726465723A3520696E736574206C69676874677261793B0D0A096865696768743A323570783B0D0A0977696474683A323570783B0D0A09766572746963616C2D616C69676E3A746F703B0D0A09637572736F723A68616E643B0D0A090D0A7D0D0A0D0A0D0A2E7472656563656C6C207B0D0A0970616464696E673A302030203220323B0D0A7D0D0A2E74726565737061636572207B0D0A0970616464696E673A303B0D0A096D617267696E3A303B0D0A096D696E2D6865696768743A3270783B0D0A09666F6E742D73697A653A3170783B0D0A0977696474683A32303070783B0D0A090D0A7D0D0A2E706F707570666F726D207B0D0A09616C69676E203A2063656E7465723B0D0A09666F6E742D73697A653A203930253B0D0A09636F6C6F72203A20626C61636B3B0D0A096261636B67726F756E642D696D6167653A2075726C28696D672F626F64792E676966293B0D0A7D0D0A0D0A2E706F7075707469746C65207B0D0A09666F6E742D73697A653A20313230253B0D0A09666F6E742D776569676874203A20626F6C643B0D0A096C65747465722D73706163696E67203A20313B0D0A7D0D0A2E706F707570746162207B0D0A09666F6E742D73697A653A20313130253B0D0A096C65747465722D73706163696E67203A20313B0D0A09626F726465722D746F70203A203120736F6C696420626C61636B3B0D0A09626F726465722D7269676874203A203120736F6C696420626C61636B3B0D0A09626F726465722D6C656674203A203120736F6C696420626C61636B3B0D0A0970616464696E67203A20343B0D0A096D617267696E203A20382033203020333B0D0A097769647468203A20313030253B0D0A096865696768743A3830253B0D0A09766572746963616C2D616C69676E3A746578742D746F703B0D0A096261636B67726F756E642D636F6C6F723A626C61636B3B0D0A09616C69676E3A63656E7465723B090D0A09636F6C6F723A626C61636B3B0D0A09637572736F723A68616E643B0D0A7D0D0A2E74616273656C6563746564207B0D0A09666F6E742D73697A653A20313130253B0D0A096C65747465722D73706163696E67203A20313B0D0A09626F72646572203A203120736F6C696420626C61636B3B0D0A09626F726465722D626F74746F6D203A20303B0D0A0970616464696E67203A20342034203020343B0D0A096D617267696E203A20303B0D0A09746578742D616C69676E203A206C6566743B0D0A09766572746963616C2D616C69676E3A746578742D746F703B0D0A09616C69676E3A63656E7465723B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B0D0A09636F6C6F723A626C61636B3B0D0A7D0D0A0D0A2E706F707570627574746F6E207B0D0A0977696474683A2031303070783B0D0A7D0D0A0D0A2E726573756C746C697374207B0D0A09616C69676E3A63656E7465723B0D0A09636F6C6F723A20626C61636B3B0D0A0977696474683A313030253B0D0A096865696768743A3839253B0D0A096F766572666C6F773A6175746F3B0D0A09706F736974696F6E3A6162736F6C7574653B0D0A096261636B67726F756E642D636F6C6F723A234530453045303B0D0A090D0A7D0D0A2E726573756C74726F77207B0D0A09666F6E742D7765696768743A6E6F726D616C3B0D0A09666F6E742D73697A653A3735253B0D0A09766572746963616C2D616C69676E3A746578742D746F703B0D0A0970616464696E673A313B0D0A096D617267696E3A303B0D0A09636F6C6F72203A20626C61636B3B0D0A09637572736F723A68616E643B0D0A096D696E2D6865696768743A313670783B0D0A7D0D0A2E726573756C7468656164696E67207B0D0A096261636B67726F756E642D636F6C6F723A234343434343433B0D0A09666F6E742D7765696768743A626F6C643B0D0A09636F6C6F723A626C61636B3B0D0A09626F726465723A33206F7574736574206C69676874677261793B0D0A096D617267696E3A3270783B0D0A0970616464696E672D6C6566743A353B0D0A09637572736F723A68616E643B0D0A09616C69676E3A63656E7465723B0D0A09666F6E742D73697A653A3835253B0D0A7D0D0A2E616374696F6E7465787461726561207B0D0A09666F6E742D73697A653A3930253B0D0A09746578742D616C69676E3A6C6566743B0D0A0977696474683A313030253B0D0A096865696768743A31303070783B0D0A7D0D0A0D0A3C2F7374796C653E0D0A0D0A3C2F686561643E0D0A3C626F6479206F6E6C6F61643D22696E697428293B22203E0D0A0D0A0D0A3C6469762069643D226D61696E626F647922203E0D0A0D0A3C666F726D206E616D653D22726573657475736572666F726D22207461726765743D225F73656C662220616374696F6E3D22736572766C65742F44727352657365745573657222206D6574686F643D22706F7374223E0D0A3C696E70757420747970653D68696464656E206E616D653D227265736574757365725F6469726964222069643D227265736574757365725F6469726964222076616C75653D22333631393031303030313A303436313832223E0D0A3C2F666F726D3E0D0A0D0A3C666F726D206E616D653D2270726573656E6365666F726D22207461726765743D225F73656C662220616374696F6E3D2244727350726573656E636522206D6574686F643D22706F7374223E0D0A3C696E70757420747970653D68696464656E206E616D653D2270726573656E63655F636F6465222069643D2270726573656E63655F636F6465222076616C75653D22223E0D0A3C696E70757420747970653D68696464656E206E616D653D2270726573656E63655F6469766572746E6272222069643D2270726573656E63655F6469766572746E6272222076616C75653D22223E0D0A3C696E70757420747970653D68696464656E206E616D653D2270726573656E63655F756E74696C222069643D2270726573656E63655F756E74696C222076616C75653D22223E0D0A3C696E70757420747970653D68696464656E206E616D653D2270726573656E63655F6469726964222069643D2270726573656E63655F6469726964222076616C75653D22223E0D0A3C696E70757420747970653D68696464656E206E616D653D2270726573656E63655F74657874222069643D2270726573656E63655F74657874222076616C75653D22223E0D0A3C696E70757420747970653D68696464656E206E616D653D2270726573656E63655F707265736574222069643D2270726573656E63655F707265736574222076616C75653D22223E0D0A3C2F666F726D3E0D0A0D0A3C64697620636C6173733D226D61696E7469746C6522207374796C653D2277696474683A31303025223E0D0A3C7461626C652063656C6C73706163696E673D302063656C6C70616464696E673D332077696474683D223130302522203E0D0A3C74723E0D0A093C746420636C6173733D226D61696E7469746C6522207374796C653D2277696474683A313030252220616C69676E3D626173656C696E653E0D0A093C696D67207372633D22696D672F7370616365722E67696622206865696768743D35302077696474683D323E0D0A0953616D62616C2042696A20202831313030290D0A3C212D2D20746F6F6C626F78202D2D3E0D0A093C746420616C69676E3D7269676874202076616C69676E3D626173656C696E65206E6F777261703E200D0A09090D0A09093C7370616E2069643D227265736574627574746F6E222020636C6173733D22616374696F6E627574746F6E22206F6E636C69636B3D2272657365745573657253657474696E677328292220203E0D0A090909093C696D67207372633D22696D672F7370616365722E676966222077696474683D22323522206865696774683D223235223E526573657420757365722073657474696E67730D0A09093C2F7370616E3E0D0A09090D0A09093C7370616E2069643D226C6F676F7574627574746F6E222020636C6173733D22616374696F6E627574746F6E22206F6E636C69636B3D226C6F676F757428292220203E0D0A090909093C696D67207372633D22696D672F7370616365722E676966222077696474683D22323522206865696774683D223235223E4C6F67206F75740D0A09093C2F7370616E3E0D0A3C74723E3C746420636F6C7370616E3D323E3C68723E0D0A0D0A3C2F7461626C653E0D0A0D0A3C2F6469763E0D0A0D0A3C64697620636C6173733D2273657474696E6773626F647922202069643D2270726573656E63656D656E75223E0D0A0D0A3C7461626C6520207374796C653D2277696474683A313030253B636F6C6F723A626C61636B3B6261636B67726F756E642D636F6C6F723A23453045304530'O & + '2220626F726465723D302063656C6C70616464696E673D332063656C6C73706163696E673D323E0D0A3C74723E3C7464207374796C653D2277696474683A3335253B626F726465723A3120736F6C696420677261793B223E0D0A0D0A093C7461626C6520207374796C653D2277696474683A313030253B636F6C6F723A626C61636B3B6261636B67726F756E642D636F6C6F723A234530453045302220626F726465723D302063656C6C70616464696E673D332063656C6C73706163696E673D323E0D0A09093C74723E3C746420207374796C653D22666F6E742D73697A653A31303025223E3C623E50726573656E63650D0A090D0A0D0A09093C7464206E6F777261703E093C696D67207372633D27696D672F6E6F745F617661696C61626C655F6E6F5F4346502E676966273E4C65667420666F7220746865206461790D0A0D0A0D0A093C74723E0D0A09093C746420636F6C7370616E3D323E3C68723E0D0A090D0A0D0A09093C7472207374796C653D22646973706C61793A223E3C746420636F6C7370616E3D323E507265646566696E6564206F7074696F6E730D0A090D0A0D0A09093C747220207374796C653D22646973706C61793A223E0D0A0909093C74642020636F6C7370616E3D32203E0D0A0909093C7370616E207374796C653D2277696474683A3730252220636C6173733D27696D67627574746F6E27206F6E636C69636B3D2270726573657450726573656E636528273027293B22203E0D0A090909093C696D67207372633D27696D672F617661696C61626C652E676966272077696474683D3136206865696768743D31363E4368616E676520746F20417661696C61626C650D0A0909093C2F7370616E3E0D0A0909093C62723E0D0A0D0A09093C747220207374796C653D22646973706C61793A223E0D0A0909093C74642020636F6C7370616E3D32203E0D0A0909093C7370616E207374796C653D2277696474683A3730252220636C6173733D27696D67627574746F6E27206F6E636C69636B3D2270726573657450726573656E636528273127293B22203E0D0A090909093C696D67207372633D27696D672F6E6F745F617661696C61626C655F6E6F5F4346502E676966272077696474683D3136206865696768743D31363E4368616E676520746F20427573790D0A0909093C2F7370616E3E0D0A0909093C62723E0D0A0D0A09093C747220207374796C653D22646973706C61793A223E0D0A0909093C74642020636F6C7370616E3D32203E0D0A0909093C7370616E207374796C653D2277696474683A3730252220636C6173733D27696D67627574746F6E27206F6E636C69636B3D2270726573657450726573656E636528273227293B22203E0D0A090909093C696D67207372633D27696D672F6E6F745F617661696C61626C655F6E6F5F4346502E676966272077696474683D3136206865696768743D31363E4368616E676520746F204D656574696E670D0A0909093C2F7370616E3E0D0A0909093C62723E0D0A0D0A09093C747220207374796C653D22646973706C61793A223E0D0A0909093C74642020636F6C7370616E3D32203E0D0A0909093C7370616E207374796C653D2277696474683A3730252220636C6173733D27696D67627574746F6E27206F6E636C69636B3D2270726573657450726573656E636528273327293B22203E0D0A090909093C696D67207372633D27696D672F6E6F745F617661696C61626C655F6E6F5F4346502E676966272077696474683D3136206865696768743D31363E4368616E676520746F204C756E63680D0A0909093C2F7370616E3E0D0A0909093C62723E0D0A0D0A09093C747220207374796C653D22646973706C61793A223E0D0A0909093C74642020636F6C7370616E3D32203E0D0A0909093C7370616E207374796C653D2277696474683A3730252220636C6173733D27696D67627574746F6E27206F6E636C69636B3D2270726573657450726573656E636528273427293B22203E0D0A090909093C696D67207372633D27696D672F6E6F745F617661696C61626C655F6E6F5F4346502E676966272077696474683D3136206865696768743D31363E4368616E676520746F204C65667420666F7220746865206461790D0A0909093C2F7370616E3E0D0A0909093C62723E0D0A0D0A09093C74723E0D0A09093C74642020636F6C7370616E3D323E3C62723E3C68723E0D0A09090D0A09093C74723E3C7464203E3C6120687265663D23206F6E636C69636B3D2273686F776D6F72656F7074696F6E73282922203E4D6F7265206F7074696F6E732E2E2E3C2F613E0D0A09090D0A0909093C7464207374796C653D22646973706C61793A6E6F6E65222069643D226D6F72656F7074696F6E73627574746F6E22206E6F7772617020616C69676E3D72696768743E3C7370616E20636C6173733D22696D67627574746F6E22207374796C653D22666F6E742D73697A653A37352522206F6E636C69636B3D2273657450726573656E636528293B223E0D0A09090909093C696D672069643D22616374696F6E696D61676522207372633D22696D672F7370616365722E676966223E266E6273703B266E6273703B0D0A090909094368616E6765206E6F773C2F7370616E3E0D0A09090D0A0D0A09093C74723E0D0A09093C746420636F6C7370616E3D323E0D0A09093C7461626C652069643D226D6F72656F7074696F6E737461626C6522207374796C653D22646973706C61793A6E6F6E65223E0D0A09093C74723E0D0A0909093C746420636F6C7370616E3D322076616C69676E3D746F70203E0D0A0909093C73656C656374207374796C653D2277696474683A31303025222069643D2270636F64656C6973742220206F6E6368616E67653D2270636F64654368616E67656428746869732922203E0D0A0909093C6F7074696F6E2076616C75653D27273E2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D3C2F6F7074696F6E3E0D0A3C6F7074696F6E2076616C75653D27315F273E42757379202D204E6F20646976657273696F6E0A3C6F7074696F6E2076616C75653D27315F2D31273E42757379202D20416C6C2063616C6C7320746F206D61696E206E756D6265720A3C6F7074696F6E2076616C75653D27315F2D32273E42757379202D20416C6C2063616C6C7320746F20766F6963656D61696C0A3C6F7074696F6E2076616C75653D27315F78273E42757379202D20416C6C2063616C6C7320746F206E756D6265720A3C6F7074696F6E2076616C75653D27273E2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D3C2F6F7074696F6E3E0A3C6F7074696F6E2076616C75653D27325F273E4D656574696E67202D204E6F20646976657273696F6E0A3C6F7074696F6E2076616C75653D27325F2D31273E4D656574696E67202D20416C6C2063616C6C7320746F206D61696E206E756D6265720A3C6F7074696F6E2076616C75653D27325F2D32273E4D656574696E67202D20416C6C2063616C6C7320746F20766F6963656D61696C0A3C6F7074696F6E2076616C75653D27325F78273E4D656574696E67202D20416C6C2063616C6C7320746F206E756D6265720A3C6F7074696F6E2076616C75653D27273E2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D3C2F6F7074696F6E3E0A3C6F7074696F6E2076616C75653D27335F273E4C756E6368202D204E6F20646976657273696F6E0A3C6F7074696F6E2076616C75653D27335F2D31273E4C756E6368202D20416C6C2063616C6C7320746F206D61696E206E756D6265720A3C6F7074696F6E2076616C75653D27335F2D32273E4C756E6368202D20416C6C2063616C6C7320746F20766F6963656D61696C0A3C6F7074696F6E2076616C75653D27335F78273E4C756E6368202D20416C6C2063616C6C7320746F206E756D6265720A3C6F7074696F6E2076616C75653D27273E2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D3C2F6F7074696F6E3E0A3C6F7074696F6E2076616C75653D27345F273E4C65667420666F722074686520646179202D204E6F20646976657273696F6E0A3C6F7074696F6E2076616C75653D27345F2D31273E4C65667420666F722074686520646179202D20416C6C2063616C6C7320746F206D61696E206E756D6265720A3C6F7074696F6E2076616C75653D27345F2D32273E4C65667420666F722074686520646179202D20416C6C2063616C6C7320746F20766F6963656D61696C0A3C6F7074696F6E2076616C75653D27345F78273E4C65667420666F722074686520646179202D20416C6C2063616C6C7320746F206E756D6265720A3C6F7074696F6E2076616C75653D27273E2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D3C2F6F7074696F6E3E0A3C6F7074696F6E2076616C75653D27355F273E52657475726E73202D204E6F20646976657273696F6E0A3C6F7074696F6E2076616C75653D27355F2D31273E52657475726E73202D20416C6C2063616C6C7320746F206D61696E206E756D6265720A3C6F7074696F6E2076616C75653D27355F2D32273E52657475726E73202D20416C6C2063616C6C7320746F20766F6963656D61696C0A3C6F7074696F6E2076616C75653D27355F78273E52657475726E73202D20416C6C2063616C6C7320746F206E756D6265720A3C6F7074696F6E2076616C75653D27273E2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D3C2F6F7074696F6E3E0A0D0A09090909090D0A0909093C2F73656C6563743E0D0A0909093C74723E3C746420636F6C7370616E3D323E0D0A090909093C696E70757420747970653D746578742076616C75653D2222206F6E6B657975703D224E756D6265724368616E67656428746869732922207374796C653D22646973706C61793A6E6F6E65222069643D22646976657273696F6E6E6272223E0D0A0D0A093C74723E0D0A093C7464207374796C653D22666F6E742D73697A653A3930253B22206E6F7772617020636F6C7370616E3D323E4261636B200D0A09093C7370616E207374796C653D22666F6E742D73697A653A373525223E284D4D2F64642F79797979293C2F7370616E3E0D0A0909093C696E70757420747970653D746578742069643D22756E74696C64617465222076616C75653D22222073697A653D223130223E0D0A09093C7370616E207374796C653D22666F6E742D73697A653A373525223E2848483A6D6D293C2F7370616E3E0D0A0909093C696E70757420747970653D746578742069643D22756E74696C74696D65222076616C75653D22222073697A653D2235223E0D0A093C74723E0D0A0909093C746420636F6C'O & + '7370616E3D322076616C69676E3D746F702077696474683D3330253E3C623E4D6573736167650D0A09090D0A09093C7472203E0909090D0A0909093C746420636F6C7370616E3D322076616C69676E3D746F70203E0D0A0909093C7465787461726561207374796C653D2277696474683A3939253B2220726F77733D3520636C6173736E616D653D22616374696F6E7465787461726561220D0A0909090969643D22705F7465787422206F6E6B6579646F776E3D22746869732E76616C75653D27273B746869732E6F6E6B6579646F776E3D6E756C6C22206F6E6B657975703D226469766D73674368616E676564287468697329223E4865726520796F752063616E20777269746520796F7572206D65737361676520746F2074686520617474656E64616E7420616E64206F74686572732E204D61782032353520636861726163746572732E3C2F74657874617265613E0D0A09090D0A09090D0A0909093C2F7461626C653E3C212D2D6D6F7265206F7074696F6E732D2D3E0D0A093C2F7461626C653E0D0A0D0A3C212D2D2043616C6C206465666C656374202D2D3E0D0A3C7464207374796C653D2277696474683A3335253B626F726465723A3120736F6C696420677261793B646973706C61793A6E6F6E65222076616C69676E3D746F703E0D0A093C7461626C6520207374796C653D22636F6C6F723A626C61636B3B6261636B67726F756E642D636F6C6F723A234530453045303B77696474683A313030252220626F726465723D302063656C6C70616464696E673D332063656C6C73706163696E673D323E0D0A09093C74723E3C7464207374796C653D22666F6E742D73697A653A31303025223E3C623E4465666C6563742063616C6C0D0A0909093C746420616C69676E3D72696768743E3C696E7075742020636C6173733D22696D67627574746F6E22207374796C653D22666F6E742D73697A653A3830253B22200D0A09090909747970653D22627574746F6E222076616C75653D224368616E676522206F6E636C69636B3D225365744465666C656374282922203E0D0A0909090D0A09093C74723E3C746420636F6C7370616E3D323E3C68723E090D0A09093C7472206F6E6D6F7573656F7665723D2274725F6D6F7573656F7665722874686973293B22206F6E6D6F7573656F75743D2274725F6D6F7573656F75742874686973292220636C6173733D74726565726F773E0D0A0909093C746420636F6C7370616E3D323E3C696E707574206F6E636C69636B3D226366436C69636B65642874686973293B2220747970653D726164696F2069643D2263665F6F70657261746F7222206E616D653D226366222076616C75653D222D3122203E266E6273703B266E6273703B4D61696E206E756D6265720D0A09093C7472206F6E6D6F7573656F7665723D2274725F6D6F7573656F7665722874686973293B22206F6E6D6F7573656F75743D2274725F6D6F7573656F75742874686973292220636C6173733D74726565726F773E0D0A0909093C746420636F6C7370616E3D323E3C696E707574206F6E636C69636B3D226366436C69636B65642874686973293B2220747970653D726164696F2069643D2263665F766F6963656D61696C22206E616D653D226366222076616C75653D222D3222203E266E6273703B266E6273703B566F6963656D61696C0D0A09093C7472206F6E6D6F7573656F7665723D2274725F6D6F7573656F7665722874686973293B22206F6E6D6F7573656F75743D2274725F6D6F7573656F75742874686973292220636C6173733D74726565726F773E0D0A0909093C746420636F6C7370616E3D323E3C696E707574206F6E636C69636B3D226366436C69636B65642874686973293B2220747970653D726164696F2069643D2263665F7822206E616D653D226366222076616C75653D225822203E266E6273703B266E6273703B50686F6E650D0A0909093C696E70757420747970653D74657874206E616D653D2263665F6E756D626572222069643D2263665F6E756D62657222206F6E6B657975703D224E756D6265724368616E6765642874686973293B22207374796C653D227669736962696C6974793A68696464656E222076616C75653D22223E0D0A09090D0A093C2F7461626C653E0D0A0D0A0D0A3C666F726D206E616D653D2263616C6C6465666C656374666F726D22207461726765743D225F73656C662220616374696F6E3D22736572766C65742F4472734465666C65637422206D6574686F643D22706F7374223E0D0A3C696E70757420747970653D68696464656E206E616D653D226469726964222069643D226469726964222076616C75653D22223E0D0A3C696E70757420747970653D68696464656E206E616D653D2263616C6C6465666C6563746E72222069643D2263616C6C6465666C6563746E72222076616C75653D22223E0D0A3C2F666F726D3E0D0A0D0A3C212D2D204344472F68756E7467726F757073202D2D3E0D0A3C7464207374796C653D2277696474683A3335253B626F726465723A3120736F6C696420677261793B222076616C69676E3D746F703E0D0A093C666F726D206E616D653D226867736574746E6722207461726765743D225F73656C662220616374696F6E3D22736572766C65742F44727348756E7447726F757022206D6574686F643D22706F7374223E0D0A093C696E70757420747970653D68696464656E206E616D653D226469726964222069643D226469726964222076616C75653D22223E0D0A093C7461626C6520207374796C653D22636F6C6F723A626C61636B3B6261636B67726F756E642D636F6C6F723A234530453045303B77696474683A313030252220626F726465723D302063656C6C70616464696E673D332063656C6C73706163696E673D323E0D0A09093C74723E3C7464207374796C653D22666F6E742D73697A653A313030253B223E3C623E41637469766174652F64656163746976617465203C62723E43616C6C20646973747269627574696F6E2067726F7570730D0A0909093C746420616C69676E3D72696768742076616C69676E3D746F703E3C696E7075742020636C6173733D22696D67627574746F6E22207374796C653D22666F6E742D73697A653A3830253B22200D0A09090909747970653D22627574746F6E222076616C75653D224368616E676522206F6E636C69636B3D22416374697661746547726F757073282922203E0D0A09093C74723E3C746420636F6C7370616E3D323E3C68723E090D0A3C74723E3C74643E4E6F74206D656D626572206F6620616E792063616C6C20646973747269627574696F6E2067726F75700A0D0A093C2F666F726D3E0D0A093C2F7461626C653E0D0A0D0A3C2F7461626C653E0D0A3C2F6469763E0D0A3C2F6469763E0D0A0D0A3C2F626F64793E0D0A3C2F68746D6C3E0D0A'O; + + // + + var integer vl_remainingStringLength := lengthof(received_reply); + var CHARSTRINGS vl_decodedMessagePieces := {}; + var HTTPMessage vloc_decodedMsg; + while( vl_remainingStringLength >0 ) + { + log("Original msg string length = ", lengthof(received_reply) ); + vl_remainingStringLength:= dec_HTTPMessage( received_reply, vloc_decodedMsg, true) + log(" The decoded message Piece = ", vloc_decodedMsg ); + log("remaining msg string length:", vl_remainingStringLength); + } + + +}//eof TC + + + function singleTC() runs on HTTP_client + { + // These may be declared as templates at global scope. + // Variables are used for performance reasons: + // sending is faster in this way. + var HeaderLines hd := { {header_name := "Host", header_value := HttpServerHostName}, + {header_name := "Content-Length", header_value := "0" } }; + // {header_name := "Connection", header_value := "close" } + + var HTTPRequest r := { client_id := omit, method := "GET", uri := "/", + version_major := 1, version_minor := 1, header := hd, body := "" }; + + var HTTPMessage send_req := { request := r }; + var Connect conn := { hostname := HttpServerHostName, + portnumber := HttpServerPort, use_ssl := HTTPClientUseSSL }; + var Close c := { client_id := omit }; + timer T_guard := 5.0; + var integer i; + var integer how_many_times := 1; //100 + + map(self:HTTP_client_port, system:HTTP_client_port); + + HTTP_client_port.send(conn); + + for(i := 0; i < how_many_times; i := i + 1 ) { + HTTP_client_port.send(send_req); + if(T_guard.running) { T_guard.stop } + + T_guard.start; + + alt { + [] HTTP_client_port.receive(recv_resp) { + if(i == how_many_times - 1) { + HTTP_client_port.send(c); + setverdict(pass); + } + } + [] HTTP_client_port.receive(h) { + HTTP_client_port.send(c); + setverdict(fail); + i := how_many_times; + } + [] HTTP_client_port.receive { + HTTP_client_port.send(c); + setverdict(fail); + } + [] T_guard.timeout { + setverdict(fail); } + }; + } + + unmap(self:HTTP_client_port, system:HTTP_client_port); + } + //================================== + //= Testcases = + //================================== + + + testcase parallel_TC_client() runs on HTTP_client + { + var HTTP_client client_PTC; + client_PTC := HTTP_client.create; + client_PTC.start(TC()); + client_PTC.done; + } + + testcase tc_parallel_server() runs on HTTP_server + { + var HTTP_server server_PTC; + server_PTC := HTTP_server.create; + server_PTC.start(server_TC()); + server_PTC.done; + } + + testcase tc_stress(in integer n) runs on HTTP_client + { + var ptcList ptc; + var integer r; + + for( r := 0; r < n; r := r + 1 ) { + ptc[r] := HTTP_client.create; + }; + + for( r := 0; r < n; r := r + 1 ) { + ptc[r].start(singleTC()); + }; + + for( r := 0; r < n; r := r + 1 ) { + ptc[r].done; + }; + } + + testcase tc_stress_Persistent_both() runs on HTTP_client + { + var HTTP_client client_PTC; + client_PTC := HTTP_client.create; + var HTTP_server server_PTC; + server_PTC := HTTP_server.create; + + server_PTC.start(server_TC()); + timer t_wait := 0.1; + t_wait.start; + t_wait.timeout; + client_PTC.start(singleTC()); + + client_PTC.done; + server_PTC.done; + } + + testcase tc_server() runs on HTTP_server + { + server_TC(); + } + + testcase tc_client() runs on HTTP_client + { + singleTC(); + } + + + testcase tc_http_encDec() runs on MTC + { + f_EncDec(); + } + + testcase tc_http_encDec2() runs on MTC + { + f_EncDec2(); + } + control + { + log("control started"); + //execute(tc_parallel_server()); + //execute(tc_stress(1)); + //execute(tc_stress_Persistent_both()); + //execute(tc_server); + //execute(tc_client); + execute(tc_http_encDec()); + execute(tc_http_encDec2()); + } + +} diff --git a/demo/HTTP_test.prj b/demo/HTTP_test.prj new file mode 100644 index 0000000000000000000000000000000000000000..d5db5774722248d24e5bae50631a60c342afac2e --- /dev/null +++ b/demo/HTTP_test.prj @@ -0,0 +1,48 @@ +<!DOCTYPE TITAN_GUI_project_file> +<Project> + <General> + <Project_Name>HTTP_test</Project_Name> + <Executable_Path>../bin/HTTP_test</Executable_Path> + <Working_Dir>../bin</Working_Dir> + <Build_Host>alpha</Build_Host> + <Execution_Mode>Parallel</Execution_Mode> + <ScriptFile_AfterMake>lssl_script</ScriptFile_AfterMake> + <Log_Format>yes</Log_Format> + <Update_Symlinks>yes</Update_Symlinks> + <Create_Absolute_Symlinks>no</Create_Absolute_Symlinks> + <Update_Makefile>yes</Update_Makefile> + <Localhost_Execute>yes</Localhost_Execute> + <Execute_Command>rsh %host "cd %project_working_dir ; "%executable" %localhost %mctr_port"</Execute_Command> + <Execute_Hosts>alfa, beta, gamma</Execute_Hosts> + <UnUsed_List></UnUsed_List> + </General> + <Modules> + <Module>../src/HTTPmsg_PortType.ttcn</Module> + <Module>../src/HTTPmsg_Types.ttcn</Module> + <Module>HTTP_Test_no_ASPs.ttcn</Module> + </Modules> + <TestPorts> + <TestPort>../src/HTTPmsg_PT.cc</TestPort> + <TestPort>../src/HTTPmsg_PT.hh</TestPort> + </TestPorts> + <Other_Sources> + <Other_Source>../../Common_Components/Abstract_Socket_CNL113384/src/Abstract_Socket.cc</Other_Source> + <Other_Source>../../Common_Components/Abstract_Socket_CNL113384/src/Abstract_Socket.hh</Other_Source> + </Other_Sources> + <Configs> + <Config>HTTP_Test.cfg</Config> + </Configs> + <Test_Cases> + <Test_Case>HTTP_Test_no_ASPs.control</Test_Case> + <Test_Case>HTTP_Test_no_ASPs.parallel_TC_client</Test_Case> + <Test_Case>HTTP_Test_no_ASPs.parallel_TC_server</Test_Case> + <Test_Case>HTTP_Test_no_ASPs.stress_TC_Persistent_both</Test_Case> + <Test_Case>HTTP_Test_no_ASPs.server_testcase</Test_Case> + <Test_Case>HTTP_Test_no_ASPs.client_testcase</Test_Case> + </Test_Cases> + <Others> + <Other>lssl_script</Other> + <Other>server.crt</Other> + <Other>server.key</Other> + </Others> +</Project> diff --git a/demo/Makefile b/demo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a85067f528489f899e7c299b4a69d6bf451b7258 --- /dev/null +++ b/demo/Makefile @@ -0,0 +1,152 @@ +# This Makefile was generated by the Makefile Generator +# of the TTCN-3 Test Executor version 1.7.pre0 build 2 +# for Attila Balasko (ethbaat@ehubuux110) on Mon Jan 15 16:28:23 2007 + +# Copyright 2000-2006 Test Competence Center, Ericsson R & D, Hungary +# For trouble reporting use the tool MTTSMS. +# For TR writers guide please visit the web page: http://ttcn.ericsson.se + +# The following make commands are available: +# - make, make all Builds the executable test suite. +# - make archive Archives all source files. +# - make check Checks the semantics of TTCN-3 and ASN.1 modules. +# - make clean Removes all generated files. +# - make compile Translates TTCN-3 and ASN.1 modules to C++. +# - make dep Creates/updates dependency list. +# - make objects Builds the object files without linking the executable. +# - make tags Creates/updates tags file using ctags. + +# +# Set these variables... +# + +# The path of your TTCN-3 Test Executor installation: +# Uncomment this line to override the environment variable. +# TTCN3_DIR = + +# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or WIN32) +PLATFORM = SOLARIS8 + +# Your C++ compiler: +CXX = g++ + +# Flags for the C++ preprocessor (and makedepend as well): +CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include + +# Flags for the C++ compiler: +CXXFLAGS = -Wall + +# Flags for the linker: +LDFLAGS = + +# Flags for the TTCN-3 and ASN.1 compiler: +COMPILER_FLAGS = -L + +# Execution mode: (either ttcn3 or ttcn3-parallel) +TTCN3_LIB = ttcn3-parallel + +# The path of your OpenSSL installation: +# If you do not have your own one, leave it unchanged. +OPENSSL_DIR = $(TTCN3_DIR) + +# Directory to store the archived source files: +# Note: you can set any directory except ./archive +ARCHIVE_DIR = backup + +# +# You may change these variables. Add your files if necessary... +# + +# TTCN-3 modules of this project: +TTCN3_MODULES = HTTP_Test_no_ASPs.ttcn HTTPmsg_PortType.ttcn HTTPmsg_Types.ttcn + +# ASN.1 modules of this project: +ASN1_MODULES = + +# C++ source & header files generated from the TTCN-3 & ASN.1 modules of +# this project: +GENERATED_SOURCES = HTTP_Test_no_ASPs.cc HTTPmsg_PortType.cc HTTPmsg_Types.cc +GENERATED_HEADERS = HTTP_Test_no_ASPs.hh HTTPmsg_PortType.hh HTTPmsg_Types.hh + +# C/C++ Source & header files of Test Ports, external functions and +# other modules: +USER_SOURCES = Abstract_Socket.cc HTTPmsg_PT.cc +USER_HEADERS = Abstract_Socket.hh HTTPmsg_PT.hh + +# Object files of this project that are needed for the executable test suite: +OBJECTS = HTTP_Test_no_ASPs.o HTTPmsg_PortType.o HTTPmsg_Types.o Abstract_Socket.o HTTPmsg_PT.o + +# Other files of the project (Makefile, configuration files, etc.) +# that will be added to the archived source files: +OTHER_FILES = Makefile + +# The name of the executable test suite: +TARGET = HTTP_Test_no_ASPs + +# +# Do not modify these unless you know what you are doing... +# Platform specific additional libraries: +# +SOLARIS_LIBS = -lsocket -lnsl -lxml2 +SOLARIS8_LIBS = -lsocket -lnsl -lxml2 +LINUX_LIBS = -lxml2 +FREEBSD_LIBS = -lxml2 +WIN32_LIBS = -lxml2 + +# +# Rules for building the executable... +# + +all: $(TARGET) ; + +objects: $(OBJECTS) ; + +$(TARGET): $(OBJECTS) + $(CXX) $(LDFLAGS) -o $@ $(OBJECTS) \ + -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \ + -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS) + +.cc.o .c.o: + $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< + +$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile + @if [ ! -f $@ ]; then rm -f compile; $(MAKE) compile; fi + +check: $(TTCN3_MODULES) $(ASN1_MODULES) + $(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) \ + $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES) + +compile: $(TTCN3_MODULES) $(ASN1_MODULES) + $(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \ + $(TTCN3_MODULES) $(ASN1_MODULES) - $? + touch $@ + +browserdata.dat: $(TTCN3_MODULES) $(ASN1_MODULES) + $(TTCN3_DIR)/bin/compiler -B -s $(COMPILER_FLAGS) \ + $(TTCN3_MODULES) $(ASN1_MODULES) + +tags: $(TTCN3_MODULES) $(ASN1_MODULES) \ +$(USER_HEADERS) $(USER_SOURCES) + $(TTCN3_DIR)/bin/ctags_ttcn3 --line-directives=yes \ + $(TTCN3_MODULES) $(ASN1_MODULES) \ + $(USER_HEADERS) $(USER_SOURCES) + +clean: + -rm -f $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) compile \ + browserdata.dat tags *.log + +dep: $(GENERATED_SOURCES) $(USER_SOURCES) + makedepend $(CPPFLAGS) $(GENERATED_SOURCES) $(USER_SOURCES) + +archive: + mkdir -p $(ARCHIVE_DIR) + tar -cvhf - $(TTCN3_MODULES) $(ASN1_MODULES) \ + $(USER_HEADERS) $(USER_SOURCES) $(OTHER_FILES) \ + | gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-`date '+%y%m%d-%H%M'`.tgz + +# +# Add your rules here if necessary... +# + +# DO NOT DELETE diff --git a/demo/installCAI.script b/demo/installCAI.script new file mode 100644 index 0000000000000000000000000000000000000000..fc9491d6eed4b85949e698e4ef67f0a890023483 --- /dev/null +++ b/demo/installCAI.script @@ -0,0 +1,80 @@ +#! /bin/sh +# Run this script from _MAIN library. It will create links in bin to all necessary +# files. If you store test ports in different location set TESTPORT_PATH variable first, +# so that this script can locate test port files. + +# Create bin/ directory if does not exist +if [ ! -d ../bin2 ] ; then mkdir ../bin2 ; fi + +# Creating softlinks from main & protocols' directories +# +# Linking non-protocol-bound files + + +# NOTE: after creating dependencies using the make utility the soft link in the bin +# directory is overwritten with a new Makefile; copy this new Makefile back to the +# _Main directory if you want to preserve it. +ln -sf ../_Main/MakefileCAI ../bin2/Makefile + +#Test Execution + +ln -sf ../CAI/PortMappingTelnet.ttcn ../bin2 +ln -sf ../_Main/CAIConfigBuild.ttcn ../bin2 +ln -sf ../_Main/TestExecCAI.ttcn ../bin2 +ln -sf ../_Main/TestExecCAI.cfg ../bin2 + + + +# Linking CAI files + +tmppath=${PROTOCOLMODULE_PATH:-'/vobs/ttcn/TCC_Common/ProtocolModules/CAI_CNL113422/src'} + +ln -sf $tmppath/CAITopLevel.ttcn ../bin2 +ln -sf $tmppath/CAICommonDefinitions.ttcn ../bin2 +ln -sf $tmppath/CAI_Cms11AC.ttcn ../bin2 +ln -sf $tmppath/CAI_Cms11Hlr.ttcn ../bin2 +ln -sf $tmppath/CAI_FmcCac.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmAAA.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmAuc.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmEir.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmFnr.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmHlr.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmMMC.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmMML.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmMMS.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmMc.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmMoIP.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmMpc.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmPps.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmVIG.ttcn ../bin2 +ln -sf $tmppath/CAI_Imsich.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmGMRM.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmIPMM.ttcn ../bin2 +ln -sf $tmppath/CAI_GsmFBC.ttcn ../bin2 +ln -sf $tmppath/CAI_EMM2_1.ttcn ../bin2 +ln -sf $tmppath/CAI_EMM2_0.ttcn ../bin2 +ln -sf $tmppath/CAI_MINSAT.ttcn ../bin2 +ln -sf $tmppath/CAI_IMT3_0.ttcn ../bin2 +ln -sf $tmppath/CAI_EPC1_0.ttcn ../bin2 + +#Encoders +ln -sf $tmppath/CAI_EncDec.cc ../bin2 +ln -sf ../CAI/CAI_DecEnc.cc ../bin2 + + +# Linking test ports + +tmppath=${TESTPORT_PATH:-'/vobs/ttcn/TCC_Common/TestPorts'} + +ln -sf $tmppath/TELNETasp_CNL113320/src/TELNETasp_PT.cc ../bin2 +ln -sf $tmppath/TELNETasp_CNL113320/src/TELNETasp_PT.hh ../bin2 +ln -sf $tmppath/TELNETasp_CNL113320/src/TELNETasp_PortType.ttcn ../bin2 +ln -sf $tmppath/HTTPmsg_CNL113312/src/HTTPmsg_Types.ttcn ../bin2 +ln -sf $tmppath/HTTPmsg_CNL113312/src/HTTPmsg_PT.cc ../bin2 +ln -sf $tmppath/HTTPmsg_CNL113312/src/HTTPmsg_PT.hh ../bin2 +ln -sf $tmppath/HTTPmsg_CNL113312/src/HTTPmsg_PortType.ttcn ../bin2 + +tmppath=${TESTPORT_PATH:-'/vobs/ttcn/TCC_Releases/TestPorts'} + +ln -sf $tmppath/Common_Components/Abstract_Socket_CNL113384/src/Abstract_Socket.cc ../bin2 +ln -sf $tmppath/Common_Components/Abstract_Socket_CNL113384/src/Abstract_Socket.hh ../bin2 diff --git a/demo/lssl_script b/demo/lssl_script new file mode 100644 index 0000000000000000000000000000000000000000..e0db83f5a8d9ded915af74c1ad21448842835711 --- /dev/null +++ b/demo/lssl_script @@ -0,0 +1,12 @@ +#!/bin/sh + +editcmd=' + +s/OPENSSL_DIR = $(TTCN3_DIR)/OPENSSL_DIR = \/mnt\/TTCN\/Tools\/openssl-0.9.8e/g + +s/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include/CPPFLAGS = -D$(PLATFORM) -DAS_USE_SSL -I$(TTCN3_DIR)\/include -I$(OPENSSL_DIR)\/include/g + +s/ -lcrypto/ -L$(OPENSSL_DIR)\/lib -lssl -lcrypto/g +' +sed -e "$editcmd" <$1 >$2 + diff --git a/demo/server.crt b/demo/server.crt new file mode 100644 index 0000000000000000000000000000000000000000..2381e9fb5405869d67d748e4e8ed89a2ee6870a3 --- /dev/null +++ b/demo/server.crt @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=HU, ST=Pest, L=Budapest, O=Ericsson Telecom Hungary, OU=RUST, CN=a99027.eth.ericsson.se/emailAddress=Eduard.Czimbalmos@ericsson.com + Validity + Not Before: Jan 8 11:39:44 2004 GMT + Not After : Jan 7 11:39:44 2005 GMT + Subject: C=HU, ST=Pest, O=Ericsson Telecom Hungary, OU=RUST, CN=a99027.eth.ericsson.se/emailAddress=Eduard.Czimbalmos@ericsson.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ac:e3:07:4b:97:49:4f:27:35:fd:c5:7f:d1:b5: + 4a:f4:3c:53:cf:bf:36:31:02:19:e0:6f:8f:a2:34: + 39:0f:d7:4f:4f:e0:4b:36:dc:5c:ef:3f:a4:fb:60: + 07:3d:50:50:d5:6f:0e:ce:60:7e:98:ed:de:b9:de: + 63:60:9b:ec:86:ff:d6:79:34:3f:e7:c2:16:d4:d3: + d8:6d:c6:a5:9f:ef:7d:7a:be:25:c1:c5:88:ec:65: + 0a:ca:c5:16:2b:3d:3d:d8:de:a8:32:b5:c4:9b:5d: + 9c:25:91:ef:65:9a:3a:9c:80:ea:95:0b:90:b0:9f: + 75:ba:aa:6d:8a:24:35:54:89 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + C1:32:B9:1E:DC:0C:44:1C:69:7F:AE:6C:85:B6:DA:59:35:0C:D2:E6 + X509v3 Authority Key Identifier: + keyid:E5:52:E4:91:CB:97:9B:48:D2:67:A3:49:EE:7E:C3:44:4B:BE:9B:2C + DirName:/C=HU/ST=Pest/L=Budapest/O=Ericsson Telecom Hungary/OU=RUST/CN=a99027.eth.ericsson.se/emailAddress=Eduard.Czimbalmos@ericsson.com + serial:00 + + Signature Algorithm: md5WithRSAEncryption + 9b:bd:ab:b4:4b:da:df:e1:f9:97:6a:37:ad:34:c8:01:6b:ba: + 20:7a:f3:77:ba:f7:d9:68:8e:f5:e6:82:dd:e3:e1:50:77:b7: + 02:39:12:4c:b9:92:2e:ac:0e:a2:1d:2e:9a:eb:50:fa:df:3e: + d3:45:57:64:9c:3f:fc:7b:d3:f1:39:ff:68:61:46:cd:68:13: + 5d:71:cf:60:9b:68:2b:87:99:31:54:3d:a9:54:27:c3:f3:eb: + 43:6c:ef:d7:bb:3d:72:f8:5b:13:e6:39:a9:f6:d7:1c:d5:23: + ca:be:3a:93:d3:39:43:a0:54:e8:29:21:cf:aa:d8:90:88:0a: + a2:c4 +-----BEGIN CERTIFICATE----- +MIIEBjCCA2+gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCSFUx +DTALBgNVBAgTBFBlc3QxETAPBgNVBAcTCEJ1ZGFwZXN0MSEwHwYDVQQKExhFcmlj +c3NvbiBUZWxlY29tIEh1bmdhcnkxDTALBgNVBAsTBFJVU1QxHzAdBgNVBAMTFmE5 +OTAyNy5ldGguZXJpY3Nzb24uc2UxLTArBgkqhkiG9w0BCQEWHkVkdWFyZC5Demlt +YmFsbW9zQGVyaWNzc29uLmNvbTAeFw0wNDAxMDgxMTM5NDRaFw0wNTAxMDcxMTM5 +NDRaMIGeMQswCQYDVQQGEwJIVTENMAsGA1UECBMEUGVzdDEhMB8GA1UEChMYRXJp +Y3Nzb24gVGVsZWNvbSBIdW5nYXJ5MQ0wCwYDVQQLEwRSVVNUMR8wHQYDVQQDExZh +OTkwMjcuZXRoLmVyaWNzc29uLnNlMS0wKwYJKoZIhvcNAQkBFh5FZHVhcmQuQ3pp +bWJhbG1vc0Blcmljc3Nvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AKzjB0uXSU8nNf3Ff9G1SvQ8U8+/NjECGeBvj6I0OQ/XT0/gSzbcXO8/pPtgBz1Q +UNVvDs5gfpjt3rneY2Cb7Ib/1nk0P+fCFtTT2G3GpZ/vfXq+JcHFiOxlCsrFFis9 +PdjeqDK1xJtdnCWR72WaOpyA6pULkLCfdbqqbYokNVSJAgMBAAGjggE9MIIBOTAJ +BgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0 +aWZpY2F0ZTAdBgNVHQ4EFgQUwTK5HtwMRBxpf65shbbaWTUM0uYwgd4GA1UdIwSB +1jCB04AU5VLkkcuXm0jSZ6NJ7n7DREu+myyhgbekgbQwgbExCzAJBgNVBAYTAkhV +MQ0wCwYDVQQIEwRQZXN0MREwDwYDVQQHEwhCdWRhcGVzdDEhMB8GA1UEChMYRXJp +Y3Nzb24gVGVsZWNvbSBIdW5nYXJ5MQ0wCwYDVQQLEwRSVVNUMR8wHQYDVQQDExZh +OTkwMjcuZXRoLmVyaWNzc29uLnNlMS0wKwYJKoZIhvcNAQkBFh5FZHVhcmQuQ3pp +bWJhbG1vc0Blcmljc3Nvbi5jb22CAQAwDQYJKoZIhvcNAQEEBQADgYEAm72rtEva +3+H5l2o3rTTIAWu6IHrzd7r32WiO9eaC3ePhUHe3AjkSTLmSLqwOoh0umutQ+t8+ +00VXZJw//HvT8Tn/aGFGzWgTXXHPYJtoK4eZMVQ9qVQnw/PrQ2zv17s9cvhbE+Y5 +qfbXHNUjyr46k9M5Q6BU6Ckhz6rYkIgKosQ= +-----END CERTIFICATE----- diff --git a/demo/server.key b/demo/server.key new file mode 100644 index 0000000000000000000000000000000000000000..8d6ece88633f8f5cb81d73de05005fa42c3523cc --- /dev/null +++ b/demo/server.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EBFCB69E20E5D263 + +KrzktC2qxWrTeP4NnRvqaI6TZWi7yyiEhSaj5/mH4RTCb2eDd6Ro+7TxTUQHVPW5 ++FVkdYIa6sMXjUmiKIiFTqcVH6uYl2SgK+tqaAIsEUIzJIYiwQh3sXMOcN3ZuFET +JYb1EypMCqFHAjfYHxFF4lJzryc5I16uOV8ajIfxvPZVcE7V5YPr9sMRxrZV8k/p +qj/TNWuDNnwJzVEtZnEUKPuHqLEXHI8kq9sqrDiDHZMAVwQb6ABpE74RfHbCYO2N +PnYZE6veiOTSZATQzjEhzGXiXslQqozRWH5iFpTI5ND00Zvm7u9AfYxgX/OWHm0/ +8SF0sxC/A+oSu00XKWVLQPvHekxGRdfqHqygdXAdlZS0BxtkUtln/ago9/QekRHL +u8O1iGz03mozFWn52VmEy9O1+V22fmpiuM95T+mzPCOwEAuN3O4BxGUkP/kwLrkY +uxeCe+Cm/3jKijMkm2ejKJhlmDS4sLuvEHG+H5C78W+7U3mNJ9/aMTTQR44H0vXz +f45OfrSt3eZsH10OoNWGk/T1EiJauOQx948bF3e6Pl4TrB2/O2GdRUKrZk5cvNQw +zHmY9JNTTPWA5rmc7HfRn7rHJ5O1eZ1P4oBA+1rTuIbqwykf1CzTWZvOH1cK77uP +0ZsL/lzJRz8NrRv768rqEm8UpDdP96XwZ9rx9euW1r+cA0NGcD+bRssm4vIWxI3F +JMG5cN2X58URsIpkTvQtA5s7XJ0y0TqMcnhtcrSz+dXyq6otT92uO3qfGZWbAdva +Gsogib7OS/BSNfvaEHIplT5u/xy4ney1G7PkoEr89WFwR6gufElJyw== +-----END RSA PRIVATE KEY----- diff --git a/doc/15517-CNL113312_EN_E_PDFV1R2.pdf b/doc/15517-CNL113312_EN_E_PDFV1R2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dcc542c739156b7d93b9298648e08e4fcce2e308 Binary files /dev/null and b/doc/15517-CNL113312_EN_E_PDFV1R2.pdf differ diff --git a/doc/19817-CNL113312_EN_G_PDFV1R2.pdf b/doc/19817-CNL113312_EN_G_PDFV1R2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b82b0e7696caed67114adbeb7373a7446fa081cc Binary files /dev/null and b/doc/19817-CNL113312_EN_G_PDFV1R2.pdf differ diff --git a/src/HTTPmsg_MessageLen.ttcn b/src/HTTPmsg_MessageLen.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..99453a847b720c007b2c41c301becdbdce46e478 --- /dev/null +++ b/src/HTTPmsg_MessageLen.ttcn @@ -0,0 +1,24 @@ +/****************************************************************************** +* Copyright (c) 2004, 2014 Ericsson AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Eduard Czimbalmos - initial implementation and initial documentation +* Istvan Ovary +* Peter Dimitrov +* Balasko Jeno +* Gabor Szalai +******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// File: HTTPmsg_MessageLen.ttcn +// Description: HTTP Message length calculator +// Rev: R8D +// Prodnr: CNL 113 469 + +module HTTPmsg_MessageLen{ + external function f_HTTPMessage_len(in octetstring stream) return integer +} diff --git a/src/HTTPmsg_MessageLen_Function.cc b/src/HTTPmsg_MessageLen_Function.cc new file mode 100644 index 0000000000000000000000000000000000000000..fd6c7fd5b188ce2938fda8e0ff785b3ed7b03903 --- /dev/null +++ b/src/HTTPmsg_MessageLen_Function.cc @@ -0,0 +1,49 @@ +/****************************************************************************** +* Copyright (c) 2004, 2014 Ericsson AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Eduard Czimbalmos - initial implementation and initial documentation +* Istvan Ovary +* Peter Dimitrov +* Balasko Jeno +* Gabor Szalai +******************************************************************************/ +// +// File: HTTPmsg_MessageLen_Function.cc +// Description: HTTP Message length calculator +// Rev: R8D +// Prodnr: CNL 113 469 + +#include "HTTPmsg_PT.hh" +#include "HTTPmsg_Types.hh" +#include "HTTPmsg_MessageLen.hh" + +using namespace HTTPmsg__Types; +using namespace HTTPmsg__PortType; + +namespace HTTPmsg__MessageLen { +INTEGER f__HTTPMessage__len(OCTETSTRING const& stream) { + HTTPMessage msg; + TTCN_Buffer *buf_p = new TTCN_Buffer() ; + buf_p->put_os(stream); + + int buf_len = buf_p->get_read_len(); + if( buf_len > 0) + { + if(f_HTTP_decodeCommon(buf_p, msg, true, false, NULL, NULL)) + { + buf_len -= buf_p->get_read_len(); + } + else + buf_len = -1; + + + } else buf_len = -1; + delete buf_p; + return buf_len; +} +} diff --git a/src/HTTPmsg_PT.cc b/src/HTTPmsg_PT.cc new file mode 100644 index 0000000000000000000000000000000000000000..71de2911ce4b05a63ff1c3cff3c7f454aa5a8c58 --- /dev/null +++ b/src/HTTPmsg_PT.cc @@ -0,0 +1,1233 @@ +/****************************************************************************** +* Copyright (c) 2004, 2014 Ericsson AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Eduard Czimbalmos - initial implementation and initial documentation +* Istvan Ovary +* Peter Dimitrov +* Balasko Jeno +* Gabor Szalai +******************************************************************************/ +// +// File: HTTPmsg_PT.cc +// Description: HTTP test port implementation +// Rev: R8D +// Prodnr: CNL 113 469 + + +#include "HTTPmsg_PT.hh" + +#include <ctype.h> +#include <arpa/inet.h> + +#ifdef AS_USE_SSL +#include <openssl/ssl.h> +#include <openssl/rand.h> +#include <openssl/err.h> +#endif + +static bool report_lf=true; + +namespace HTTPmsg__PortType { + +HTTPmsg__PT::HTTPmsg__PT(const char *par_port_name) + : HTTPmsg__PT_BASE(par_port_name) +{ + parameter_set(use_connection_ASPs_name(), "yes"); + parameter_set(server_backlog_name(), "1024"); + use_notification_ASPs = false; + set_ttcn_buffer_usercontrol(true); + set_handle_half_close(true); + adding_client_connection = false; + adding_ssl_connection = false; + server_use_ssl = false; +#ifdef AS_USE_SSL + + set_ssl_use_ssl(true); +#endif +} + +HTTPmsg__PT::~HTTPmsg__PT() +{ + +} + +void HTTPmsg__PT::set_parameter(const char *parameter_name, + const char *parameter_value) +{ + log_debug("entering HTTPmsg__PT::set_parameter(%s, %s)", parameter_name, parameter_value); + if(strcasecmp(parameter_name, use_notification_ASPs_name()) == 0) { + if (strcasecmp(parameter_value,"yes")==0) use_notification_ASPs = true; + else if (strcasecmp(parameter_value,"no")==0) use_notification_ASPs = false; + else log_error("Parameter value '%s' not recognized for parameter '%s'", parameter_value, use_notification_ASPs_name()); + } + else if((strcasecmp(parameter_name, use_connection_ASPs_name()) == 0) || !parameter_set(parameter_name ,parameter_value)) { + log_warning("HTTPmsg__PT::set_parameter(): Unsupported Test Port parameter: %s", parameter_name); + } + log_debug("leaving HTTPmsg__PT::set_parameter(%s, %s)", parameter_name, parameter_value); +} + +void HTTPmsg__PT::Handle_Fd_Event(int fd, + boolean is_readable, boolean is_writable, boolean is_error) +{ + log_debug("-------------- entering HTTPmsg__PT::Handle_Fd_Event() - event received on a connection"); + Handle_Socket_Event(fd, is_readable, is_writable, is_error); + log_debug("leaving HTTPmsg__PT::Handle_Fd_Event()"); +} + +void HTTPmsg__PT::Handle_Timeout(double time_since_last_call) +{ + log_debug("entering HTTPmsg__PT::Handle_Timeout()"); + Handle_Timeout_Event(time_since_last_call); + log_debug("leaving HTTPmsg__PT::Handle_Timeout()"); +} + +void HTTPmsg__PT::user_map(const char *system_port) +{ + log_debug("entering HTTPmsg__PT::user_map(%s)",system_port); + if(TTCN_Logger::log_this_event(TTCN_DEBUG)) { + if(!get_socket_debugging()) + log_warning("%s: to switch on HTTP test port debugging, set the '*.%s.http_debugging := \"yes\" in the port's parameters.", get_name(), get_name()); + } + map_user(); + log_debug("leaving HTTPmsg__PT::user_map()"); +} + +void HTTPmsg__PT::user_unmap(const char *system_port) +{ + log_debug("entering HTTPmsg__PT::user_unmap(%s)",system_port); + + unmap_user(); + + log_debug("leaving HTTPmsg__PT::user_unmap()"); +} + +void HTTPmsg__PT::user_start() +{ +} + +void HTTPmsg__PT::user_stop() +{ +} + +void HTTPmsg__PT::outgoing_send(const HTTPmsg__Types::Close& send_par) +{ + log_debug("entering HTTPmsg__PT::outgoing_send(Close)"); + + if(send_par.client__id().ispresent()) + remove_client((int)send_par.client__id()()); + else + remove_all_clients(); + + log_debug("leaving HTTPmsg__PT::outgoing_send(Close)"); +} + +void HTTPmsg__PT::outgoing_send(const HTTPmsg__Types::Connect& send_par) +{ + log_debug("entering HTTPmsg__PT::outgoing_send(Connect)"); + + adding_ssl_connection = send_par.use__ssl(); + adding_client_connection = true; + +#ifndef AS_USE_SSL + if(adding_ssl_connection) + { + log_error("%s: HTTP test port is not compiled to support SSL connections. Please check the User's Guide for instructions on compiling the HTTP test port with SSL support.", get_name()); + } +#endif + + int client_id = open_client_connection(send_par.hostname(),int2str((INTEGER)send_par.portnumber()),NULL,NULL); + + adding_ssl_connection = false; + adding_client_connection = false; + + log_debug("leaving HTTPmsg__PT::outgoing_send(Connect),client_id: %d", client_id); +} + +void HTTPmsg__PT::outgoing_send(const HTTPmsg__Types::Listen& send_par) +{ + log_debug("entering HTTPmsg__PT::outgoing_send(Listen)"); + + server_use_ssl = send_par.use__ssl(); + + if(server_use_ssl) + { + #ifndef AS_USE_SSL + log_error("%s: HTTP test port is not compiled to support SSL connections. Please check the User's Guide for instructions on compiling the HTTP test port with SSL support.", get_name()); + #endif + } + + if(send_par.local__hostname().ispresent()) + { + + open_listen_port(send_par.local__hostname()(),int2str((INTEGER)send_par.portnumber())); + + } + else + { + log_debug("using IN_ADDR_ANY as local host name"); + open_listen_port(NULL,int2str((INTEGER)send_par.portnumber())); + + } + + log_debug("leaving HTTPmsg__PT::outgoing_send(Listen)"); + +} + +void HTTPmsg__PT::outgoing_send(const HTTPmsg__Types::Half__close& send_par) +{ + log_debug("entering HTTPmsg__PT::outgoing_send(Half_close)"); + + if(send_par.client__id().ispresent()) + send_shutdown((int)send_par.client__id()()); + else + send_shutdown(); + + log_debug("leaving HTTPmsg__PT::outgoing_send(Half_close)"); + +} + +void HTTPmsg__PT::outgoing_send(const HTTPmsg__Types::Shutdown& /*send_par*/) +{ + log_debug("entering HTTPmsg__PT::outgoing_send(Shutdown)"); + + close_listen_port(); + + log_debug("leaving HTTPmsg__PT::outgoing_send(Shutdown)"); +} + +void HTTPmsg__PT::outgoing_send(const HTTPmsg__Types::HTTPMessage& send_par) +{ + log_debug("entering HTTPmsg__PT::outgoing_send(HTTPMessage)"); + + TTCN_Buffer snd_buf; + int client_id = -1; + + switch(send_par.get_selection()) + { + case HTTPmsg__Types::HTTPMessage::ALT_request: + { + if(send_par.request().client__id().ispresent()) + client_id = send_par.request().client__id()(); + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_request__binary: + { + if(send_par.request__binary().client__id().ispresent()) + client_id = send_par.request__binary().client__id()(); + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_response: + { + if(send_par.response().client__id().ispresent()) + client_id = send_par.response().client__id()(); + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_response__binary: + { + if(send_par.response__binary().client__id().ispresent()) + client_id = send_par.response__binary().client__id()(); + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_erronous__msg: + { + if(send_par.erronous__msg().client__id().ispresent()) + client_id = send_par.erronous__msg().client__id()(); + break; + } + default: + TTCN_error("Unknown HTTP_Message type to encode and send!"); + } + + f_HTTP_encodeCommon(send_par, snd_buf); + + if(client_id >= 0) + send_outgoing(snd_buf.get_data(), snd_buf.get_len(), client_id); + else + send_outgoing(snd_buf.get_data(), snd_buf.get_len()); + + log_debug("leaving HTTPmsg__PT::outgoing_send(HTTPMessage)"); +} + +void HTTPmsg__PT::client_connection_opened(int client_id) +{ + log_debug("entering HTTPmsg__PT::client_connection_opened(%d)", client_id); + + if(use_notification_ASPs) + { + HTTPmsg__Types::Connect__result asp; + asp.client__id() = client_id; + incoming_message(asp); + } + else if(client_id < 0) + log_error("Cannot connect to server"); + + log_debug("leaving HTTPmsg__PT::client_connection_opened()"); +} + +void HTTPmsg__PT::listen_port_opened(int port_number) +{ + log_debug("entering HTTPmsg__PT::listen_port_opened(%d)", port_number); + + if(use_notification_ASPs) + { + HTTPmsg__Types::Listen__result asp; + asp.portnumber() = port_number; + incoming_message(asp); + } + else if(port_number < 0) + log_error("Cannot listen at port"); + + log_debug("leaving HTTPmsg__PT::listen_port_opened()"); +} + +void HTTPmsg__PT::message_incoming(const unsigned char* /*msg*/, int /*messageLength*/, int client_id) +{ + log_debug("entering HTTPmsg__PT::message_incoming()"); + + TTCN_Buffer* buf_p = get_buffer(client_id); + + while(buf_p->get_read_len() > 0) + { + log_debug("HTTPmsg__PT::message_incoming(): decoding next message, len: %d", (int)buf_p->get_read_len()); + if(!HTTP_decode(buf_p, client_id)) + break; + } + + log_debug("leaving HTTPmsg__PT::message_incoming()"); +} + +void HTTPmsg__PT::peer_half_closed(int client_id) +{ + log_debug("entering HTTPmsg__PT::peer_half_closed(client_id: %d)", client_id); + + TTCN_Buffer* buf_p = get_buffer(client_id); + buf_p->rewind(); + while(buf_p->get_read_len() > 0) + { + log_debug("HTTPmsg__PT::remove_client(): decoding next message, len: %d", (int)buf_p->get_read_len()); + if(!HTTP_decode(buf_p, client_id,true)) + break; + } + + HTTPmsg__Types::Half__close asp; + asp.client__id() = client_id; + incoming_message(asp); + + log_debug("leaving HTTPmsg__PT::peer_half_closed(client_id: %d)", client_id); +} + +void HTTPmsg__PT::peer_disconnected(int client_id) +{ + log_debug("entering HTTPmsg__PT::peer_disconnected(client_id: %d)", client_id); + + if(use_notification_ASPs) + { + HTTPmsg__Types::Close asp; + asp.client__id() = client_id; + incoming_message(asp); + } + else Abstract_Socket::peer_disconnected(client_id); + + log_debug("leaving HTTPmsg__PT::peer_disconnected(client_id: %d)", client_id); +} + +//void HTTPmsg__PT::peer_connected(int client_id, sockaddr_in& addr) + +void HTTPmsg__PT::peer_connected(int client_id, const char * host, const int port) +{ + log_debug("entering HTTPmsg__PT::peer_connected(%d)", client_id); + + if(use_notification_ASPs) + { + HTTPmsg__Types::Client__connected asp; + asp.hostname() = host; + asp.portnumber() = port; + asp.client__id() = client_id; + + incoming_message(asp); + } + else Abstract_Socket::peer_connected(client_id, host, port); + + log_debug("leaving HTTPmsg__PT::peer_connected()"); +} + +bool HTTPmsg__PT::add_user_data(int client_id) +{ + log_debug("entering HTTPmsg__PT::add_user_data(client_id: %d, use_ssl: %s)", + client_id, (adding_client_connection && adding_ssl_connection) || (server_use_ssl && !adding_ssl_connection) ? "yes" : "no"); + + set_server_mode(!adding_client_connection); + + if((adding_client_connection && !adding_ssl_connection) || (!adding_client_connection && !server_use_ssl)) + { + log_debug("leaving HTTPmsg__PT::add_user_data() with returning Abstract_Socket::add_user_data()"); + return Abstract_Socket::add_user_data(client_id); + } + else + { +#ifdef AS_USE_SSL + log_debug("leaving HTTPmsg__PT::add_user_data() with returning SSL_Socket::add_user_data()"); + return SSL_Socket::add_user_data(client_id); +#else + log_error("%s: HTTP test port is not compiled to support SSL connections. Please check the User's Guide for instructions on compiling the HTTP test port with SSL support.", get_name()); +#endif + } + + // Programming error in HTTPmsg__PT::add_user_data() + return false; +} + +bool HTTPmsg__PT::remove_user_data(int client_id) +{ + log_debug("entering HTTPmsg__PT::remove_user_data(client_id: %d", client_id); + +#ifdef AS_USE_SSL + if(get_user_data(client_id)) + { + // INFO: it is assumed that only SSL_Socket assigns user data to each peer + log_debug("leaving HTTPmsg__PT::remove_user_data() with returning SSL_Socket::remove_user_data()"); + return SSL_Socket::remove_user_data(client_id); + } +#endif + + log_debug("leaving HTTPmsg__PT::remove_user_data() with returning Abstract_Socket::remove_user_data()"); + return Abstract_Socket::remove_user_data(client_id); +} + +int HTTPmsg__PT::receive_message_on_fd(int client_id) +{ + log_debug("entering HTTPmsg__PT::receive_message_on_fd(client_id: %d)", client_id); + +#ifdef AS_USE_SSL + if(get_user_data(client_id)) + { + // INFO: it is assumed that only SSL_Socket assigns user data to each peer + log_debug("leaving HTTPmsg__PT::receive_message_on_fd() with returning SSL_Socket::receive_message_on_fd()"); + return SSL_Socket::receive_message_on_fd(client_id); + } +#endif + + log_debug("leaving HTTPmsg__PT::receive_message_on_fd() with returning Abstract_Socket::receive_message_on_fd()"); + return Abstract_Socket::receive_message_on_fd(client_id); +} + +void HTTPmsg__PT::remove_client(int client_id) +{ + log_debug("entering HTTPmsg__PT::remove_client(client_id: %d)", client_id); + + TTCN_Buffer* buf_p = get_buffer(client_id); + + while(buf_p->get_read_len() > 0) + { + log_debug("HTTPmsg__PT::remove_client(): decoding next message, len: %d", (int)buf_p->get_read_len()); + if(!HTTP_decode(buf_p, client_id,true)) + break; + } + +#ifdef AS_USE_SSL + if(get_user_data(client_id)) + { + // INFO: it is assumed that only SSL_Socket assigns user data to each peer + log_debug("leaving HTTPmsg__PT::remove_client() with returning SSL_Socket::remove_client()"); + return SSL_Socket::remove_client(client_id); + } +#endif + + log_debug("leaving HTTPmsg__PT::remove_client() with returning Abstract_Socket::remove_client()"); + return Abstract_Socket::remove_client(client_id); +} + +int HTTPmsg__PT::send_message_on_fd(int client_id, const unsigned char * message_buffer, int length_of_message) +{ + log_debug("entering HTTPmsg__PT::send_message_on_fd(client_id: %d)", client_id); + +#ifdef AS_USE_SSL + if(get_user_data(client_id)) + { + // INFO: it is assumed that only SSL_Socket assigns user data to each peer + log_debug("leaving HTTPmsg__PT::send_message_on_fd() with returning SSL_Socket::send_message_on_fd()"); + return SSL_Socket::send_message_on_fd(client_id, message_buffer, length_of_message); + } +#endif + + log_debug("leaving HTTPmsg__PT::send_message_on_fd() with returning Abstract_Socket::send_message_on_fd()"); + return Abstract_Socket::send_message_on_fd(client_id, message_buffer, length_of_message); +} + + +// HTTP specific functions + +// replaced by f_HTTP_encodeCommon: +// void HTTPmsg__PT::HTTP_encode(const HTTPmsg__Types::HTTPMessage& msg, TTCN_Buffer& buf) +// { +// f_HTTP_encodeCommon( msg, buf); +// } + +//Encodes msg type of "HTTPMessage" into buffer +void f_HTTP_encodeCommon(const HTTPmsg__Types::HTTPMessage& msg, TTCN_Buffer& buf) +{ + buf.clear(); + if( msg.get_selection() == HTTPmsg__Types::HTTPMessage::ALT_erronous__msg ) + buf.put_cs(msg.erronous__msg().msg()); + else + { + const HTTPmsg__Types::HeaderLines* header = NULL; + const HTTPmsg__Types::HTTPRequest* request = NULL; + const HTTPmsg__Types::HTTPResponse* response = NULL; + const HTTPmsg__Types::HTTPRequest__binary__body* request_binary = NULL; + const HTTPmsg__Types::HTTPResponse__binary__body* response_binary = NULL; + const CHARSTRING* body = NULL; + const OCTETSTRING* body_binary = NULL; + + if(msg.get_selection() == HTTPmsg__Types::HTTPMessage::ALT_request) + { + request = &msg.request(); + header = &request->header(); + body = &request->body(); + buf.put_cs(request->method()); + buf.put_c(' '); + buf.put_cs(request->uri()); + buf.put_cs(" HTTP/"); + buf.put_cs(int2str(request->version__major())); + buf.put_c('.'); + buf.put_cs(int2str(request->version__minor())); + buf.put_cs("\r\n"); + } + else if(msg.get_selection() == HTTPmsg__Types::HTTPMessage::ALT_response) + { + response = &msg.response(); + header = &response->header(); + body = &response->body(); + buf.put_cs("HTTP/"); + buf.put_cs(int2str(response->version__major())); + buf.put_c('.'); + buf.put_cs(int2str(response->version__minor())); + buf.put_c(' '); + buf.put_cs(int2str(response->statuscode())); + buf.put_c(' '); + buf.put_cs(response->statustext()); + buf.put_cs("\r\n"); + } + else if(msg.get_selection() == HTTPmsg__Types::HTTPMessage::ALT_request__binary) + { + request_binary = &msg.request__binary(); + header = &request_binary->header(); + body_binary = &request_binary->body(); + buf.put_cs(request_binary->method()); + buf.put_c(' '); + buf.put_cs(request_binary->uri()); + buf.put_cs(" HTTP/"); + buf.put_cs(int2str(request_binary->version__major())); + buf.put_c('.'); + buf.put_cs(int2str(request_binary->version__minor())); + buf.put_cs("\r\n"); + } + else if(msg.get_selection() == HTTPmsg__Types::HTTPMessage::ALT_response__binary) + { + response_binary = &msg.response__binary(); + header = &response_binary->header(); + body_binary = &response_binary->body(); + buf.put_cs("HTTP/"); + buf.put_cs(int2str(response_binary->version__major())); + buf.put_c('.'); + buf.put_cs(int2str(response_binary->version__minor())); + buf.put_c(' '); + buf.put_cs(int2str(response_binary->statuscode())); + buf.put_c(' '); + buf.put_cs(response_binary->statustext()); + buf.put_cs("\r\n"); + } + + for( int i = 0; i < header->size_of(); i++ ) + { + buf.put_cs((*header)[i].header__name()); + buf.put_cs(": "); + buf.put_cs((*header)[i].header__value()); + buf.put_cs("\r\n"); + } + + buf.put_cs("\r\n"); + + if(body && body->lengthof() > 0) + { + buf.put_cs(*body); + } + else if(body_binary && body_binary->lengthof() > 0) + { + buf.put_os(*body_binary); + } + } +} + +bool HTTPmsg__PT::HTTP_decode(TTCN_Buffer* buffer, const int client_id, const bool connection_closed) +{ + + //HTTPmsg__Types::HTTPMessage * msg = new HTTPmsg__Types::HTTPMessage(); + + HTTPmsg__Types::HTTPMessage msg; + + if(f_HTTP_decodeCommon(buffer, msg, connection_closed, get_socket_debugging(), test_port_type, test_port_name )) + { + TTCN_Logger::log(TTCN_DEBUG,"HTTPmsg__PT::HTTP_decode, before calling incoming_message"); + f_setClientId(msg,client_id); + incoming_message(msg); + TTCN_Logger::log(TTCN_DEBUG,"HTTPmsg__PT::HTTP_decode, after calling incoming_message"); + return true; + } + return false; +} + +void f_setClientId( HTTPmsg__Types::HTTPMessage& msg, const int client_id) +{ + switch(msg.get_selection()) + { + case HTTPmsg__Types::HTTPMessage::ALT_request: + { + msg.request().client__id()=client_id; + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_request__binary: + { + msg.request__binary().client__id()=client_id; + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_response: + { + msg.response().client__id()=client_id; + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_response__binary: + { + msg.response__binary().client__id()=client_id; + break; + } + case HTTPmsg__Types::HTTPMessage::ALT_erronous__msg: //is this case redundant code(?) + { + msg.erronous__msg().client__id()=OMIT_VALUE; + break; + } + default: + break; + }//switch + return; +}//f_setClientId + +// +// returns with true if the buffer is not empty and it contain valid message +// Postcondition: if buffer contains valid message, msg will contain the first decoded HTTP message, the decoded part will be removed from the buffer +bool f_HTTP_decodeCommon( TTCN_Buffer* buffer, HTTPmsg__Types::HTTPMessage& msg, const bool connection_closed, + const bool socket_debugging, const char *test_port_type, const char *test_port_name) +{ + + TTCN_Logger::log(TTCN_DEBUG, "starting f_HTTP_decodeCommon "); + if(buffer->get_read_len() <= 0) + return FALSE; + + buffer->rewind(); + + Decoding_Params decoding_params; + decoding_params.non_persistent_connection = FALSE; + decoding_params.chunked_body = FALSE; + decoding_params.content_length = -1; + decoding_params.error = FALSE; + decoding_params.isMessage = TRUE; + + if (TTCN_Logger::log_this_event(TTCN_DEBUG)) + { + if( test_port_name!= NULL) + TTCN_Logger::log(TTCN_DEBUG, "%s DECODER: <%s>\n", test_port_name, + (const char*)CHARSTRING(buffer->get_read_len(), (const char*)buffer->get_read_data())); + else + TTCN_Logger::log(TTCN_DEBUG, "DECODER: <%s>\n", + (const char*)CHARSTRING(buffer->get_read_len(), (const char*)buffer->get_read_data())); + } + + CHARSTRING first; + bool isResponse; + + // Decoding the first line + + switch(get_line(buffer, first, false)) + { + case TRUE: // The first line is available + { + //HTTPmsg__Types::HTTPMessage msg; + HTTPmsg__Types::HeaderLines header = NULL_VALUE; + OCTETSTRING body=OCTETSTRING(0, (const unsigned char*)""); + const char *cc_first = (const char *)first; + //fprintf(stderr, "first: %s\n", cc_first); + int version__major, version__minor, statusCode; + + char* method_name; + const char* pos = strchr(cc_first, ' '); + if(pos == NULL) + { + TTCN_Logger::log(TTCN_DEBUG, "could not find space in the first line of response: <%s>", cc_first); + decoding_params.isMessage = FALSE; + decoding_params.error = TRUE; + break; + } + method_name = (char*)Malloc(pos - cc_first + 1); + strncpy(method_name, cc_first, pos - cc_first); + method_name[pos - cc_first] = '\0'; + + char* stext = (char*)Malloc(strlen(cc_first)); + + TTCN_Logger::log(TTCN_DEBUG, "method_name: <%s>", method_name); + if(strncasecmp(method_name, "HTTP/", 5) == 0) + { + // The first line contains a response like HTTP/1.1 200 OK + isResponse = true; + + if(sscanf(cc_first, "HTTP/%d.%d %d %[^\r]", &version__major, &version__minor, + &statusCode, stext) != 4) + { + decoding_params.isMessage = FALSE; + decoding_params.error = TRUE; + Free(method_name); + Free(stext); + break; + } + if (version__minor == 0) + decoding_params.non_persistent_connection = TRUE; + } + else + { + isResponse = false; + // The first line contains a request + // like "POST / HTTP/1.0" + if(sscanf(pos + 1, "%s HTTP/%d.%d", + stext, &version__major, &version__minor ) != 3) + { + decoding_params.isMessage = FALSE; + decoding_params.error = TRUE; + Free(method_name); + Free(stext); + break; + } + } + + // Additional header lines + TTCN_Logger::log(TTCN_DEBUG, "Decoding the headers"); + HTTP_decode_header(buffer, header, decoding_params, socket_debugging, isResponse, test_port_type, test_port_name); + TTCN_Logger::log(TTCN_DEBUG, "Headers decoded. %s headers.", decoding_params.isMessage ? "Valid" : "Invalid"); + + if(isResponse && decoding_params.content_length==-1){ + if( (statusCode>99 && statusCode <200) || statusCode==204 || statusCode==304 ) decoding_params.content_length=0; + } + + if(decoding_params.isMessage) + HTTP_decode_body(buffer, body, decoding_params, connection_closed, socket_debugging, test_port_type, test_port_name); + + if(decoding_params.isMessage) + { + TTCN_Logger::log(TTCN_DEBUG, "Message successfully decoded"); + bool foundBinaryCharacter = false; + + int len = body.lengthof(); + const unsigned char* ptr = (const unsigned char*)body; + for(int i = 0; i < len && !foundBinaryCharacter; i++) + { + if(!isascii(ptr[i])) + foundBinaryCharacter = true; + } + if(foundBinaryCharacter) + TTCN_Logger::log(TTCN_DEBUG, "Binary data found"); + if(isResponse) + { + if(foundBinaryCharacter) + { + HTTPmsg__Types::HTTPResponse__binary__body& response_binary = msg.response__binary(); + response_binary.client__id() = OMIT_VALUE; + response_binary.version__major() = version__major; + response_binary.version__minor() = version__minor; + response_binary.statuscode() = statusCode; + if(strlen(stext) > 0) + response_binary.statustext() = CHARSTRING(stext); + else + response_binary.statustext() = ""; + response_binary.header() = header; + response_binary.body() = body; + } + else + { + HTTPmsg__Types::HTTPResponse& response = msg.response(); + response.client__id() = OMIT_VALUE; + response.version__major() = version__major; + response.version__minor() = version__minor; + response.statuscode() = statusCode; + if(strlen(stext) > 0) + response.statustext() = CHARSTRING(stext); + else + response.statustext() = ""; + response.header() = header; + response.body() = oct2char(body); + } + } + else + { + if(foundBinaryCharacter) + { + HTTPmsg__Types::HTTPRequest__binary__body& request_binary = msg.request__binary(); + request_binary.client__id() = OMIT_VALUE; + request_binary.method() = CHARSTRING(method_name); + request_binary.uri() = CHARSTRING(stext); + request_binary.version__major() = version__major; + request_binary.version__minor() = version__minor; + request_binary.header() = header; + request_binary.body() = body; + } + else + { + HTTPmsg__Types::HTTPRequest& request = msg.request(); + request.client__id() = OMIT_VALUE; + request.method() = CHARSTRING(method_name); + request.uri() = CHARSTRING(stext); + request.version__major() = version__major; + request.version__minor() = version__minor; + request.header() = header; + request.body() = oct2char(body); + } + } + //incoming_message(msg); <- outer function calls if necessary + } + Free(method_name); + Free(stext); + } + break; + case BUFFER_CRLF: + case BUFFER_FAIL: + decoding_params.error = TRUE; + case FALSE: + decoding_params.isMessage = FALSE; + } + + if(decoding_params.error) + { + + if(buffer->get_read_len() > 0) + msg.erronous__msg().msg() = CHARSTRING(buffer->get_read_len(), (const char*)buffer->get_read_data()); + else + msg.erronous__msg().msg() = "The previous message is erronous."; + msg.erronous__msg().client__id() = OMIT_VALUE; + //incoming_message(msg); + buffer->clear(); + decoding_params.isMessage = TRUE; + } + + if(decoding_params.isMessage) + { + buffer->cut(); + } + + return decoding_params.isMessage; +} + +void HTTP_decode_header(TTCN_Buffer* buffer, HTTPmsg__Types::HeaderLines& headers, Decoding_Params& decoding_params, + const bool socket_debugging, const bool resp, const char *test_port_type, const char *test_port_name) +{ + CHARSTRING cstr; + const char* separator; + char* header_name = NULL; + bool length_received = false; + + for(int i = 0; ; i++) + { + switch(get_line(buffer, cstr, true)) + { + case TRUE: + { + char h[cstr.lengthof() + 1]; + strcpy(h, (const char*)cstr); + separator = strchr(h, ':'); + if(separator) + { + header_name = (char*)Realloc(header_name, separator - h + 1); + strncpy(header_name, h, separator - h); + header_name[separator - h] = '\0'; + separator++; + while(*separator && isspace(separator[0])) + separator++; + char* end = h + strlen(h); + while(isspace((end - 1)[0])) + { + end--; + *end = '\0'; + } + headers[i] = HTTPmsg__Types::HeaderLine(header_name, separator); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "+Header line: <%s: %s>", header_name, separator); + + if(!strcasecmp(header_name, "Content-Length")) + { sscanf(separator, "%d", &decoding_params.content_length); length_received=true;} + else if(!strcasecmp(header_name, "Connection") && !strcasecmp(separator, "close")) + decoding_params.non_persistent_connection = TRUE; + else if(!strcasecmp(header_name, "Connection") && !strcasecmp(separator, "keep-alive")) + decoding_params.non_persistent_connection = FALSE; + else if(!strcasecmp(header_name, "Transfer-Encoding") && !strcasecmp(separator, "chunked")) + decoding_params.chunked_body = TRUE; + + } + continue; + } + case BUFFER_FAIL: + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "BUFFER_FAIL in HTTP_decode_header!"); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "whole bufer now: <%s>", (const char*)buffer->get_data()); + log_to_hexa(buffer); + decoding_params.error = TRUE; + case FALSE: + decoding_params.isMessage = FALSE; + case BUFFER_CRLF: + break; + } + break; + } + if(decoding_params.isMessage && !resp && !length_received && !decoding_params.chunked_body) decoding_params.content_length=0; + Free(header_name); +} + +void HTTP_decode_body(TTCN_Buffer* buffer, OCTETSTRING& body, Decoding_Params& decoding_params, const bool connection_closed, + const bool socket_debugging, const char *test_port_type, const char *test_port_name) +{ + if(buffer->get_read_len() > 0) + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "Decoding body, buffer length: %d", buffer->get_read_len()); + + if (decoding_params.chunked_body) + { + HTTP_decode_chunked_body(buffer, body, decoding_params, socket_debugging, test_port_type, test_port_name); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "--------- After chunked body decoding:"); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "--------- non_persistent_connection: %s", decoding_params.non_persistent_connection ? "yes" : "no"); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "--------- chunked_body: %s", decoding_params.chunked_body ? "yes" : "no"); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "--------- content_length: %d", decoding_params.content_length); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "--------- error: %s", decoding_params.error ? "yes" : "no"); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "--------- isMessage: %s", decoding_params.isMessage ? "yes" : "no"); + + } + else if(decoding_params.content_length >= 0) + { + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "lengthof body: %d, content_length given: %d", buffer->get_read_len(), decoding_params.content_length); + if(buffer->get_read_len() >= (unsigned)decoding_params.content_length) + { + body = OCTETSTRING(decoding_params.content_length, buffer->get_read_data()); + buffer->set_pos(buffer->get_pos() + decoding_params.content_length); + } + else + { + decoding_params.isMessage = FALSE; + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "The decoder's body length %d is less than the Content_length in the message header %d; The HTTP port is waiting for additional data.", buffer->get_read_len(), decoding_params.content_length); + buffer->set_pos(buffer->get_pos() + buffer->get_read_len()); + } + } + else if(connection_closed) + { + /* if(buffer->get_read_len() >= 0)*/ // Always true + { + body = OCTETSTRING(buffer->get_read_len(), buffer->get_read_data()); + buffer->set_pos(buffer->get_pos() + buffer->get_read_len()); + } + } else { + decoding_params.isMessage = FALSE; + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "The HTTP port is waiting for additional data."); + buffer->set_pos(buffer->get_pos() + buffer->get_read_len()); + } +} + +void HTTP_decode_chunked_body(TTCN_Buffer* buffer, OCTETSTRING& body, Decoding_Params& decoding_params, + const bool socket_debugging, const char *test_port_type, const char *test_port_name) +{ + OCTETSTRING chunk; + CHARSTRING line; + unsigned int chunk_size = 1; + + while(chunk_size > 0) + { + switch(get_line(buffer, line, false)) + { + case TRUE: + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "line: <%s>", (const char*)line); + if(sscanf((const char *)line, "%x", &chunk_size) != 1) + { + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "No chunksize found"); + body = body + OCTETSTRING(line.lengthof(), (const unsigned char*)(const char*)line); + chunk_size = 0; + decoding_params.error = TRUE; + } + else + { + if(chunk_size == 0) + { + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "chunk_size 0 -> closing chunk"); + if(get_line(buffer, line, false) == BUFFER_CRLF) + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "Trailing \\r\\n ok!"); + else + TTCN_Logger::log(TTCN_WARNING,"Trailing \\r\\n after the closing chunk is not present, instead it is <%s>!", (const char*)line); + } +/* else if(chunk_size < 0) // the chunk_size is unsigned, never true + { + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "chunk_size less than 0"); + decoding_params.error = TRUE; + chunk_size = 0; + }*/ + else // chunk_size > 0 + { + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "processing next chunk, size: %d", chunk_size); + if(buffer->get_read_len() < chunk_size) + { + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "chunk size is greater than the buffer length, more data is needed"); + decoding_params.isMessage = FALSE; + chunk_size = 0; + } + } + } + break; + case FALSE: + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "buffer does not contain a whole line, more data is needed"); + decoding_params.isMessage = FALSE; + chunk_size = 0; + break; + case BUFFER_CRLF: + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "beginning CRLF removed"); + continue; + case BUFFER_FAIL: + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "BUFFER_FAIL"); + decoding_params.error = FALSE; + chunk_size = 0; + break; + default: + decoding_params.isMessage = FALSE; + chunk_size = 0; + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "more data is needed"); + } + + body = body + OCTETSTRING(chunk_size, buffer->get_read_data()); + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "pull %d bytes from %d", chunk_size, buffer->get_read_len()); + buffer->set_pos(buffer->get_pos() + chunk_size); + // hack + if(buffer->get_read_data()[0] == '\n') + { + TTCN_Logger::log(TTCN_WARNING, "hack: adjusted buffer position after the '\\n'"); + buffer->set_pos(buffer->get_pos() + 1); + } + HTTPmsg__Types::log_debug(socket_debugging, test_port_type, test_port_name, "remaining data: <%s>, len: %d", (const char *)CHARSTRING(buffer->get_read_len(), (const char*)buffer->get_read_data()), buffer->get_read_len()); + } +} + +int get_line(TTCN_Buffer* buffer, CHARSTRING& to, const bool concatenate_header_lines) +{ + unsigned int i = 0; + const unsigned char *cc_to = buffer->get_read_data(); + + if(!buffer->get_read_len()) + return FALSE; + + while(1) + { + for( ; i < buffer->get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++); + + if(i >= buffer->get_read_len()) + { + to = CHARSTRING(""); + return FALSE; + } + else + { + if(cc_to[i] == '\n') {// + if(report_lf){ + switch(HTTPmsg__Types::crlf__mode){ + case HTTPmsg__Types::strict__crlf__mode::ERROR_: + return BUFFER_FAIL; + break; + case HTTPmsg__Types::strict__crlf__mode::WARNING__ONCE: + report_lf=false; + // no break + case HTTPmsg__Types::strict__crlf__mode::WARNING: + TTCN_warning("Missing '\\r'."); + break; + default: + break; + } + } + if(i > 0 && (i + 1) < buffer->get_read_len() && concatenate_header_lines && (cc_to[i+1] == ' ' || cc_to[i+1] == '\t')) + i += 1; + else + { + to = CHARSTRING(i, (const char*)cc_to); + buffer->set_pos(buffer->get_pos() + i + 1); + return i == 0 ? BUFFER_CRLF : TRUE; + } + + } else + { + if((i + 1) < buffer->get_read_len() && cc_to[i + 1] != '\n') + return BUFFER_FAIL; + else if(i > 0 && (i + 2) < buffer->get_read_len() && concatenate_header_lines && (cc_to[i+2] == ' ' || cc_to[i+2] == '\t')) + i += 2; + else + { + to = CHARSTRING(i, (const char*)cc_to); + buffer->set_pos(buffer->get_pos() + i + 2); + return i == 0 ? BUFFER_CRLF : TRUE; + } + } + } + } +} + +void log_to_hexa(TTCN_Buffer* buffer) +{ + int len = buffer->get_read_len(); + const unsigned char* ptr = buffer->get_read_data(); + for(int i = buffer->get_pos(); i < len; i++) + { + TTCN_Logger::log_event(" %02X", ptr[i]); + } +} + + +const char* HTTPmsg__PT::local_port_name() { return "";} +const char* HTTPmsg__PT::remote_address_name() { return "";} +const char* HTTPmsg__PT::local_address_name() { return "";} +const char* HTTPmsg__PT::remote_port_name() { return "";} +const char* HTTPmsg__PT::use_notification_ASPs_name() { return "use_notification_ASPs";} +const char* HTTPmsg__PT::halt_on_connection_reset_name(){ return "";} +const char* HTTPmsg__PT::server_mode_name() { return "";} +const char* HTTPmsg__PT::socket_debugging_name() { return "http_debugging";} +const char* HTTPmsg__PT::nagling_name() { return "";} +const char* HTTPmsg__PT::server_backlog_name() { return "server_backlog";} +const char* HTTPmsg__PT::ssl_use_ssl_name() { return "";} +const char* HTTPmsg__PT::ssl_use_session_resumption_name() { return "";} +const char* HTTPmsg__PT::ssl_private_key_file_name() { return "KEYFILE";} +const char* HTTPmsg__PT::ssl_trustedCAlist_file_name() { return "TRUSTEDCALIST_FILE";} +const char* HTTPmsg__PT::ssl_certificate_file_name() { return "CERTIFICATEFILE";} +const char* HTTPmsg__PT::ssl_password_name() { return "PASSWORD";} +const char* HTTPmsg__PT::ssl_verifycertificate_name() { return "VERIFYCERTIFICATE";} + + +} //eof namespace "HTTPmsg__PortType" + +namespace HTTPmsg__Types { + +using namespace HTTPmsg__PortType; + +//========================================================================= +//==== Working Functions independent from sending and receiving:=== +//========================================================================= + +//from AbstractSocket +void log_debug(const bool socket_debugging, const char *test_port_type, const char *test_port_name, const char *fmt, ...) +{ + if (socket_debugging) { + TTCN_Logger::begin_event(TTCN_DEBUG); + if ((test_port_type!=NULL && test_port_name!=NULL)&&(strlen(test_port_type)!=0 && strlen(test_port_name)!=0)) + TTCN_Logger::log_event("%s test port (%s): ", test_port_type, test_port_name); + va_list args; + va_start(args, fmt); + TTCN_Logger::log_event_va_list(fmt, args); + va_end(args); + TTCN_Logger::end_event(); + } +} + +void log_warning(const char *test_port_type, const char *test_port_name, const char *fmt, ...) +{ + TTCN_Logger::begin_event(TTCN_WARNING); + if (test_port_type!=NULL && test_port_name!=NULL) + TTCN_Logger::log_event("%s test port (%s): ", test_port_type, test_port_name); + va_list args; + va_start(args, fmt); + TTCN_Logger::log_event_va_list(fmt, args); + va_end(args); + TTCN_Logger::end_event(); +} + +//========================================================================= +//==== Encoder-decoder Functions independent from sending and receiving:=== +//========================================================================= + +/********************************************************* +* Function: enc__HTTPMessage +* +* Purpose: +* To encode msg type of HTTPMessage into OCTETSTRING separated from sending functionality +* It is for users using this test port as a protocol module +* +* References: +* RFC2616 +* +* Precondition: +* msg is filled in properly +* Postcondition: +* +* +* Parameters: +* msg - the HTTP Message to be encoded +* +* Return Value: +* OCTETSTRING - the encoded message +* Detailed Comments: +* - +* +*********************************************************/ +OCTETSTRING enc__HTTPMessage( const HTTPmsg__Types::HTTPMessage& msg ) { + TTCN_Buffer buf; + buf.clear(); + HTTPmsg__PortType::f_HTTP_encodeCommon( msg, buf); + return OCTETSTRING(buf.get_len(), buf.get_data()); +} +/********************************************************* +* Function: dec__HTTPMessage +* +* Purpose: +* To decode msg type of OCTETSTRING into HTTPMessage separated from receiving functionality +* It is for users using this test port as a protocol module +* +* References: +* RFC2616 +* +* Precondition: +* stream is filled in properly +* Postcondition: +* - +* +* Parameters: +* stream - the message to be decoded +* msg - reference to the record type of HTTPMessage which will contain the decoded value if the return value less than the length of the original stream +* Return Value: +* integer - the length of the remaining data which is not decoded yet. +* Detailed Comments: +* If the full stream is decoded, the return value is zero +* If nothing is decoded (decoding failed) the return value equals to the original length of the stream +* +*********************************************************/ + +INTEGER dec__HTTPMessage(OCTETSTRING const& stream, HTTPMessage& msg, const BOOLEAN& socket_debugging = dec__HTTPMessage_socket__debugging_defval ) +{ + TTCN_Logger::log(TTCN_DEBUG, "starting HTTPmsg__Types::dec__HTTPMessage"); + TTCN_Buffer *buf_p = new TTCN_Buffer() ; + buf_p->put_os(stream); + + int buf_len = buf_p->get_read_len(); + if( buf_len > 0) + { + if(f_HTTP_decodeCommon(buf_p, msg, true, socket_debugging, NULL, NULL)) + { + log_debug(socket_debugging,"","","dec__HTTPMessage, after decoding:\nbuf_len: %d\nget_len: %d\nget_read_len:%d", + buf_len, + buf_p->get_len(), + buf_p->get_read_len()); + buf_len = buf_p->get_read_len(); //remaining data length + } + else + buf_len = -1; + + + } else buf_len = -1; + delete buf_p; + return buf_len; +} + +}//namespace diff --git a/src/HTTPmsg_PT.hh b/src/HTTPmsg_PT.hh new file mode 100644 index 0000000000000000000000000000000000000000..3d3f6ebbc0e14f9167f4728c390c3d0615263b7d --- /dev/null +++ b/src/HTTPmsg_PT.hh @@ -0,0 +1,161 @@ +/****************************************************************************** +* Copyright (c) 2004, 2014 Ericsson AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Eduard Czimbalmos - initial implementation and initial documentation +* Istvan Ovary +* Peter Dimitrov +* Balasko Jeno +* Gabor Szalai +******************************************************************************/ +// +// File: HTTPmsg_PT.hh +// Description: HTTP test port header file +// Rev: R8D +// Prodnr: CNL 113 469 + + +#ifndef HTTPmsg__PT_HH +#define HTTPmsg__PT_HH + +#include "HTTPmsg_PortType.hh" +#include "Abstract_Socket.hh" + +#define BUFFER_FAIL 2 +#define BUFFER_CRLF 3 +//============================== +namespace HTTPmsg__PortType { +//============================== +typedef struct { + bool non_persistent_connection; + bool chunked_body; + int content_length; + bool error; + bool isMessage; +} Decoding_Params; + +#ifdef AS_USE_SSL +class HTTPmsg__PT : public SSL_Socket, public HTTPmsg__PT_BASE { +#else + class HTTPmsg__PT : public Abstract_Socket, public HTTPmsg__PT_BASE { +#endif + +public: + + HTTPmsg__PT(const char *par_port_name = NULL); + ~HTTPmsg__PT(); + + void set_parameter(const char *parameter_name, const char *parameter_value); + +protected: + void user_map(const char *system_port); + void user_unmap(const char *system_port); + + void user_start(); + void user_stop(); + + void outgoing_send(const HTTPmsg__Types::Close& send_par); + void outgoing_send(const HTTPmsg__Types::Connect& send_par); + void outgoing_send(const HTTPmsg__Types::Listen& send_par); + void outgoing_send(const HTTPmsg__Types::Half__close& send_par); + void outgoing_send(const HTTPmsg__Types::Shutdown& send_par); + void outgoing_send(const HTTPmsg__Types::HTTPMessage& send_par); + + const char* local_port_name(); + const char* remote_address_name(); + const char* local_address_name(); + const char* remote_port_name(); + const char* use_notification_ASPs_name(); + const char* halt_on_connection_reset_name(); + const char* server_mode_name(); + const char* socket_debugging_name(); + const char* nagling_name(); + const char* server_backlog_name(); + const char* ssl_use_ssl_name(); + const char* ssl_use_session_resumption_name(); + const char* ssl_private_key_file_name(); + const char* ssl_trustedCAlist_file_name(); + const char* ssl_certificate_file_name(); + const char* ssl_password_name(); + const char* ssl_verifycertificate_name(); + + void message_incoming(const unsigned char* msg, int length, int client_id = -1); + void Add_Fd_Read_Handler(int fd) { Handler_Add_Fd_Read(fd); } + void Add_Fd_Write_Handler(int fd) { Handler_Add_Fd_Write(fd); } + void Remove_Fd_Read_Handler(int fd) { Handler_Remove_Fd_Read(fd); } + void Remove_Fd_Write_Handler(int fd) { Handler_Remove_Fd_Write(fd); } + void Remove_Fd_All_Handlers(int fd) { Handler_Remove_Fd(fd); } + void Handler_Uninstall() { Uninstall_Handler(); } + void Timer_Set_Handler(double call_interval, boolean is_timeout = TRUE, + boolean call_anyway = TRUE, boolean is_periodic = TRUE) { + Handler_Set_Timer(call_interval, is_timeout, call_anyway, is_periodic); + } + +// overriden functions in order to distinguish between normal and SSL connections + virtual bool add_user_data(int client_id); + virtual bool remove_user_data(int client_id); + virtual int send_message_on_fd(int client_id, const unsigned char * message_buffer, int length_of_message); + virtual int receive_message_on_fd(int client_id); + virtual void client_connection_opened(int client_id); + virtual void listen_port_opened(int port_number); + virtual void peer_connected(int client_id, const char * host, const int port); + + + virtual void peer_disconnected(int client_id); + virtual void peer_half_closed(int client_id); + virtual void remove_client(int client_id); + +// HTTP specific functions + + // returns encoded message in buf + //void HTTP_encode(const HTTPmsg__Types::HTTPMessage &msg, TTCN_Buffer& buf); //replaced by f_HTTP_encodeCommon + bool HTTP_decode(TTCN_Buffer*, const int, const bool connection_closed = false); + //void HTTP_decode_header(TTCN_Buffer*, HTTPmsg__Types::HeaderLines&, Decoding_Params&); //moved outside the class + //void HTTP_decode_body(TTCN_Buffer*, OCTETSTRING&, Decoding_Params&, const bool); //moved outside the class + //void HTTP_decode_chunked_body(TTCN_Buffer*, OCTETSTRING&, Decoding_Params&); //moved outside the class + +private: + void Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error); + void Handle_Timeout(double time_since_last_call); + + //int get_line(TTCN_Buffer*, CHARSTRING&, const bool concatenate_header_lines = true); + //void log_to_hexa(TTCN_Buffer*); + + bool adding_ssl_connection; + bool adding_client_connection; + bool server_use_ssl; + + bool use_notification_ASPs; +}; +//=================================== +//== Functions outside the class: === +//=================================== +void f_setClientId( HTTPmsg__Types::HTTPMessage& msg, const int client_id); +void f_HTTP_encodeCommon(const HTTPmsg__Types::HTTPMessage& msg, TTCN_Buffer& buf); +bool f_HTTP_decodeCommon(TTCN_Buffer* buffer,HTTPmsg__Types::HTTPMessage& msg, const bool connection_closed, + const bool socket_debugging, const char *test_port_type, const char *test_port_name); +int get_line(TTCN_Buffer* buffer, CHARSTRING& to, const bool concatenate_header_lines); +void log_to_hexa(TTCN_Buffer*); + +void HTTP_decode_header(TTCN_Buffer*, HTTPmsg__Types::HeaderLines&, Decoding_Params&,const bool socket_debugging, const bool resp,const char *test_port_type, const char *test_port_name); + +void HTTP_decode_body(TTCN_Buffer*, OCTETSTRING&, Decoding_Params&, const bool, + const bool socket_debugging, const char *test_port_type, const char *test_port_name); + +void HTTP_decode_chunked_body(TTCN_Buffer*, OCTETSTRING&, Decoding_Params&, + const bool socket_debugging, const char *test_port_type, const char *test_port_name); +}//namespace + +//============================== +namespace HTTPmsg__Types +//=============================== +{ +void log_debug(const bool socket_debugging, const char *test_port_type, const char *test_port_name, const char *fmt, ...); +void log_warning(const char *test_port_type, const char *test_port_name, const char *fmt, ...); +} + +#endif diff --git a/src/HTTPmsg_PortType.ttcn b/src/HTTPmsg_PortType.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..f56fdde08a77c89b86269cb3850710d9a64fee84 --- /dev/null +++ b/src/HTTPmsg_PortType.ttcn @@ -0,0 +1,41 @@ +/****************************************************************************** +* Copyright (c) 2004, 2014 Ericsson AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Eduard Czimbalmos - initial implementation and initial documentation +* Istvan Ovary +* Peter Dimitrov +* Balasko Jeno +* Gabor Szalai +******************************************************************************/ +// +// File: HTTPmsg_Types.ttcn +// Description: HTTP port type definition +// Rev: R8D +// Prodnr: CNL 113 469 + + +module HTTPmsg_PortType +{ + import from HTTPmsg_Types all; + + type port HTTPmsg_PT message + { + // Connection handling ASPs + inout Close; + out Connect; + in Connect_result; + in Client_connected; + inout Half_close; + out Listen; + in Listen_result; + inout Shutdown; + + // Message to send and receive + inout HTTPMessage; + }; +} diff --git a/src/HTTPmsg_Types.ttcn b/src/HTTPmsg_Types.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..c7ef281966d5b0940885ef514a4e27a545fce03d --- /dev/null +++ b/src/HTTPmsg_Types.ttcn @@ -0,0 +1,153 @@ +/****************************************************************************** +* Copyright (c) 2004, 2014 Ericsson AB +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* Eduard Czimbalmos - initial implementation and initial documentation +* Istvan Ovary +* Peter Dimitrov +* Balasko Jeno +* Gabor Szalai +******************************************************************************/ +// +// File: HTTPmsg_Types.ttcn +// Description: HTTP Message and TCP connection handling ASP types +// Rev: R8D +// Prodnr: CNL 113 469 + + +module HTTPmsg_Types { + +modulepar { + boolean tsp_socket_debugging := false; + strict_crlf_mode crlf_mode:=WARNING_ONCE; +} + +external function enc_HTTPMessage( in HTTPMessage msg) return octetstring; +external function dec_HTTPMessage( in octetstring stream, inout HTTPMessage msg, in boolean socket_debugging := tsp_socket_debugging) return integer; + + +type enumerated strict_crlf_mode {ERROR, WARNING, WARNING_ONCE, ACCEPT}; +/* Basic types */ + +type record HeaderLine { + charstring header_name, + charstring header_value +}; + +type record of HeaderLine HeaderLines; + +type record HTTPResponse { + // client_id is used only in case of multiple connections, otherwise set it to omit + integer client_id optional, + integer version_major, + integer version_minor, + integer statuscode, + charstring statustext, + HeaderLines header, + charstring body +}; + +type record HTTPRequest { + // client_id is used only in case of multiple connections, otherwise set it to omit + integer client_id optional, + charstring method, + charstring uri, + integer version_major, + integer version_minor, + HeaderLines header, + charstring body +}; + +type record HTTPResponse_binary_body { + // client_id is used only in case of multiple connections, otherwise set it to omit + integer client_id optional, + integer version_major, + integer version_minor, + integer statuscode, + charstring statustext, + HeaderLines header, + octetstring body +}; + +type record HTTPRequest_binary_body { + // client_id is used only in case of multiple connections, otherwise set it to omit + integer client_id optional, + charstring method, + charstring uri, + integer version_major, + integer version_minor, + HeaderLines header, + octetstring body +}; + +type record HTTP_erronous_msg { + // client_id is used only in case of multiple connections, otherwise set it to omit + integer client_id optional, + charstring msg +} + +type union HTTPMessage { + HTTPResponse response, + HTTPRequest request, + HTTPResponse_binary_body response_binary, + HTTPRequest_binary_body request_binary, + HTTP_erronous_msg erronous_msg +}; + +/* + * Connection handling ASPs + */ + +// Closes all connections, or the specified one only. +// client_id = omit means close all connections. +// Close comes when a connection gets disconnected +type record Close { + // when sending, client_id shall be used in case of multiple connections + // when receiving, client_id determines the client which has disconnected + integer client_id optional +}; + +type record Connect { + charstring hostname, + integer portnumber, + boolean use_ssl +}; + +// Received by the client after Connect is sent. +// The client_id will be filled with -1 if unsuccessful. +// Returned client_id shall be used to distinguish between the open connections. +type record Connect_result { + integer client_id +} + +// Received when the server has accepted an incoming connection. +type record Client_connected { + charstring hostname, + integer portnumber (1..65535), + integer client_id +}; + +// Sent when the local end of the connection has to be shut down for writing. +// Received when the remote end of the connection has been shut down for writing. +type record Half_close { + integer client_id optional +}; + +type record Listen { + charstring local_hostname optional, + integer portnumber, + boolean use_ssl +}; + +// Received after Listen. Sends back the listening port number, -1 on fail +type record Listen_result { + integer portnumber (-1..65535) +}; + +type record Shutdown {}; + +}