Commit 28dc8eb2be6606adf9bac40e2c3b7f1b033d1a82

Authored by totoro
1 parent ec1c6c0b

BufferedConnection type is now public, since it uses by XML_RPC

remove the use of dead_line, DenialOfService and SState which was no longer in use in the Calexium lib
web/CXM_multihost_http_server.anubis
... ... @@ -694,20 +694,29 @@ type EncodingType:
694 694 www_url,
695 695 multipart_form_data.
696 696  
697   -type BufferedConnection:
  697 +public type BufferedConnection:
698 698 buffered_connection(Connection conn,
699 699 Var(ByteArray) buffer,
700   - Var(Int) read_pos).
701   -
  700 + Var(Int) read_pos,
  701 + Var(List(Word8)) unput_chars // for reading requests
  702 + ).
702 703  
703 704  
  705 +public define BufferedConnection
  706 + buffered_connection
  707 + (
  708 + Connection conn
  709 + )=
  710 + buffered_connection(conn, var(constant_byte_array(0, 0)), var(0), var([]))
  711 + .
  712 +
704 713 *** [2] Tools.
705 714  
706 715 *** [2.1] Formating an error message.
707 716  
708 717 The next function formats an error message.
709 718  
710   -define String
  719 +public define String
711 720 format
712 721 (
713 722 Error msg
... ... @@ -751,7 +760,7 @@ define String
751 760 public type SState:
752 761 sstate
753 762 (
754   - Var(List(Word8)) unput_chars, // for reading requests
  763 + //Var(List(Word8)) unput_chars, // for reading requests
755 764 Var(Int) sttm, // 'start time'
756 765 Var(Int) uploaded_file_count
757 766 ).
... ... @@ -775,8 +784,8 @@ public type SState:
775 784 define One
776 785 unput // unputting a character (add it in front of the list)
777 786 (
778   - Word8 character,
779   - SState s
  787 + Word8 character,
  788 + BufferedConnection s
780 789 ) =
781 790 s.unput_chars <- (List(Word8))[character . *(s.unput_chars)].
782 791  
... ... @@ -880,13 +889,12 @@ define Result(Error,Word8)
880 889 next_char // reading a character (check the list first, and read on the connection
881 890 // only when the list is empty).
882 891 (
883   - BufferedConnection connection,
884   - Int dead_line,
885   - DenialOfService dos,
886   - SState s
  892 + BufferedConnection connection
  893 +// Int dead_line,
  894 +// DenialOfService dos
887 895 ) =
888 896 //with t2_tmp = (UTime) now,
889   - if *(s.unput_chars) is
  897 + if *(connection.unput_chars) is
890 898 {
891 899 [ ] then
892 900 // ///////////////////
... ... @@ -930,17 +938,16 @@ define Result(Error,Word8)
930 938 // },
931 939  
932 940 [h . t] then
933   - s.unput_chars <- t; //accumulate_t2(t2_tmp);
  941 + connection.unput_chars <- t; //accumulate_t2(t2_tmp);
934 942 ok(h)
935 943 }.
936 944  
937 945 define ByteArray
938 946 get_and_erase_buffer
939 947 (
940   - BufferedConnection connection,
941   - SState s
  948 + BufferedConnection connection
942 949 )=
943   - with head = to_byte_array(implode(*s.unput_chars)),
  950 + with head = to_byte_array(implode(*connection.unput_chars)),
944 951 tail = extract(*connection.buffer, *connection.read_pos, length(*connection.buffer)),
945 952 // println("--- get_and_erase_buffer ----");
946 953 // println("unput char length : "+length(to_string(head)));
... ... @@ -953,7 +960,7 @@ define ByteArray
953 960 // println("["+to_string(*connection.buffer)+"]");
954 961 // println(" -- tail content ");
955 962 // println("["+to_string(tail)+"]");
956   - s.unput_chars <- [];
  963 + connection.unput_chars <- [];
957 964 connection.buffer <- constant_byte_array(0,0);
958 965 connection.read_pos <- 0;
959 966 head + tail
... ... @@ -970,20 +977,19 @@ define ByteArray
970 977 just before the body of a request.
971 978  
972 979 define Result(Error,One)
973   - read_and_ignore
974   - (
975   - BufferedConnection connection, // to client
976   - Int dead_line,
977   - Int number_of_characters, // number of characters to read and ignore
978   - DenialOfService dos,
979   - SState s
980   - ) =
981   - if number_of_characters =< 0 then ok(unique) else
982   - if next_char(connection, dead_line, dos, s) is
983   - {
984   - error(msg) then error(msg),
985   - ok(c) then read_and_ignore(connection,dead_line,number_of_characters-1,dos, s)
986   - }.
  980 + read_and_ignore
  981 + (
  982 + BufferedConnection connection, // to client
  983 + Int number_of_characters // number of characters to read and ignore
  984 + ) =
  985 + if number_of_characters =< 0 then
  986 + ok(unique)
  987 + else
  988 + if next_char(connection) is
  989 + {
  990 + error(msg) then error(msg),
  991 + ok(c) then read_and_ignore(connection, number_of_characters-1)
  992 + }.
987 993  
988 994  
989 995  
... ... @@ -1001,28 +1007,25 @@ define Result(Error,One)
1001 1007 define Result(Error,String)
1002 1008 read_string
1003 1009 (
1004   - BufferedConnection connection, // connection with the client
1005   - Int dead_line,
1006   - List(Word8) so_far, // characters read so far (in reverse order)
1007   - DenialOfService dos,
1008   - SState s
  1010 + BufferedConnection connection, // connection with the client
  1011 + List(Word8) so_far // characters read so far (in reverse order)
1009 1012 ) =
1010   - if next_char(connection, dead_line,dos, s) is
  1013 + if next_char(connection) is
1011 1014 {
1012 1015 error(msg) then error(msg),
1013 1016 ok(c) then
1014 1017 if c = '\\'
1015   - then if next_char(connection,dead_line,dos, s) is
  1018 + then if next_char(connection) is
1016 1019 {
1017 1020 error(msg) then error(msg),
1018 1021 ok(d) then
1019 1022 if d = '\"'
1020   - then read_string(connection,dead_line,['\"' . so_far],dos, s)
1021   - else read_string(connection,dead_line,[d, c . so_far],dos, s)
  1023 + then read_string(connection,['\"' . so_far])
  1024 + else read_string(connection,[d, c . so_far])
1022 1025 }
1023 1026 else if c = '\"'
1024 1027 then ok(implode(reverse(so_far)))
1025   - else read_string(connection,dead_line,[c . so_far],dos, s)
  1028 + else read_string(connection,[c . so_far])
1026 1029 }.
1027 1030  
1028 1031  
... ... @@ -1304,34 +1307,31 @@ define Bool
1304 1307 define Result(Error,One)
1305 1308 skip_http_blanks
1306 1309 (
1307   - BufferedConnection connection,
1308   - Int dead_line,
1309   - DenialOfService dos,
1310   - SState s
  1310 + BufferedConnection connection
1311 1311 ) =
1312   - if next_char(connection, dead_line, dos, s) is
  1312 + if next_char(connection) is
1313 1313 {
1314 1314 error(msg) then error(msg),
1315 1315 ok(c) then
1316 1316 if is_strict_blank(c)
1317   - then skip_http_blanks(connection, dead_line, dos, s)
  1317 + then skip_http_blanks(connection)
1318 1318 else if c = 13
1319   - then if next_char(connection, dead_line, dos, s) is
  1319 + then if next_char(connection) is
1320 1320 {
1321 1321 error(msg) then error(msg), // (unput(c); ok(unique)),
1322 1322 ok(d) then
1323 1323 if d = 10
1324   - then if next_char(connection, dead_line, dos, s) is
  1324 + then if next_char(connection) is
1325 1325 {
1326 1326 error(msg) then error(msg), // (unput(d); unput(c); ok(unique)),
1327 1327 ok(e) then
1328 1328 if is_strict_blank(e)
1329   - then skip_http_blanks(connection, dead_line, dos, s)
1330   - else (unput(e, s); unput(d, s); unput(c, s); ok(unique))
  1329 + then skip_http_blanks(connection)
  1330 + else (unput(e, connection); unput(d, connection); unput(c, connection); ok(unique))
1331 1331 }
1332   - else (unput(d, s); unput(c, s); ok(unique))
  1332 + else (unput(d, connection); unput(c, connection); ok(unique))
1333 1333 }
1334   - else (unput(c, s); ok(unique))
  1334 + else (unput(c, connection); ok(unique))
1335 1335 }.
1336 1336  
1337 1337  
... ... @@ -1358,39 +1358,59 @@ define Result(Error,One)
1358 1358 come. This is the reason for 'read_and_ignore' above, which is used precisely for
1359 1359 reading that last (13,10) pair.
1360 1360  
1361   -define Result(Error,One)
1362   - read_new_line
1363   - (
1364   - BufferedConnection connection,
1365   - Int dead_line,
1366   - DenialOfService dos,
1367   - SState s
1368   - ) =
1369   - if skip_http_blanks(connection, dead_line, dos, s) is
1370   - {
1371   - error(msg) then error(msg),
1372   - ok(_) then
1373   - if next_char(connection, dead_line, dos, s) is
1374   - {
1375   - error(msg) then error(msg),
1376   - ok(c) then
1377   - if c = 13
1378   - then if next_char(connection, dead_line, dos, s) is
1379   - {
1380   - error(msg) then error(msg),
1381   - ok(d) then
1382   - if d = 10
1383   - then ok(unique)
1384   - else (unput(d, s);
1385   - unput(c, s);
1386   - error(end_of_line_expected))
1387   - }
1388   - else (unput(c, s);
1389   - error(end_of_line_expected))
1390   - }}.
1391   -
  1361 +public define Result(Error,One)
  1362 + read_new_line
  1363 + (
  1364 + BufferedConnection connection
  1365 + ) =
  1366 + if skip_http_blanks(connection) is
  1367 + {
  1368 + error(msg) then error(msg),
  1369 + ok(_) then
  1370 + if next_char(connection) is
  1371 + {
  1372 + error(msg) then error(msg),
  1373 + ok(c) then
  1374 + if c = 13
  1375 + then if next_char(connection) is
  1376 + {
  1377 + error(msg) then error(msg),
  1378 + ok(d) then
  1379 + if d = 10
  1380 + then ok(unique)
  1381 + else (unput(d, connection);
  1382 + unput(c, connection);
  1383 + println("1");
  1384 + error(end_of_line_expected))
  1385 + }
  1386 + else (unput(c, connection);
  1387 + println("2");
  1388 + error(end_of_line_expected))
  1389 + }}.
1392 1390  
1393 1391  
  1392 +public define Result(Error,One)
  1393 + skip_line
  1394 + (
  1395 + BufferedConnection connection
  1396 + ) =
  1397 + if next_char(connection) is
  1398 + {
  1399 + error(msg) then error(msg),
  1400 + ok(c) then
  1401 + if c = 13 then
  1402 + if next_char(connection) is
  1403 + {
  1404 + error(msg) then error(msg),
  1405 + ok(d) then
  1406 + if d = 10 then
  1407 + ok(unique)
  1408 + else
  1409 + skip_line(connection)
  1410 + }
  1411 + else
  1412 + skip_line(connection)
  1413 + }.
1394 1414  
1395 1415  
1396 1416  
... ... @@ -1412,42 +1432,36 @@ define Result(Error,String)
1412 1432 read_word_aux
1413 1433 (
1414 1434 BufferedConnection connection,
1415   - Int dead_line,
1416   - List(Word8) so_far,
1417   - DenialOfService dos,
1418   - SState s
  1435 + List(Word8) so_far
1419 1436 ) =
1420   - if next_char(connection,dead_line,dos, s) is
1421   - {
1422   - error(msg) then error(msg),
1423   - ok(c) then
1424   - if is_blank(c)
1425   - then (unput(c, s);
1426   - ok(implode(reverse(so_far))))
1427   - else read_word_aux(connection,dead_line,[c . so_far],dos, s)
1428   - }.
  1437 + if next_char(connection) is
  1438 + {
  1439 + error(msg) then error(msg),
  1440 + ok(c) then
  1441 + if is_blank(c)
  1442 + then (unput(c, connection);
  1443 + ok(implode(reverse(so_far))))
  1444 + else read_word_aux(connection,[c . so_far])
  1445 + }.
1429 1446  
1430 1447 define Result(Error,String)
1431   - read_word
1432   - (
1433   - BufferedConnection connection,
1434   - Int dead_line,
1435   - DenialOfService dos,
1436   - SState s
1437   - ) =
1438   - if skip_http_blanks(connection,dead_line,dos, s) is
1439   - {
1440   - error(msg) then error(msg),
1441   - ok(_) then
1442   - if next_char(connection, dead_line, dos, s) is
1443   - {
1444   - error(msg) then error(msg),
1445   - ok(c) then
1446   - if c = '\"'
1447   - then read_string(connection,dead_line,[],dos, s)
1448   - else read_word_aux(connection,dead_line,[c],dos, s)
1449   - }
1450   - }.
  1448 + read_word
  1449 + (
  1450 + BufferedConnection connection
  1451 + ) =
  1452 + if skip_http_blanks(connection) is
  1453 + {
  1454 + error(msg) then error(msg),
  1455 + ok(_) then
  1456 + if next_char(connection) is
  1457 + {
  1458 + error(msg) then error(msg),
  1459 + ok(c) then
  1460 + if c = '\"'
  1461 + then read_string(connection,[])
  1462 + else read_word_aux(connection,[c])
  1463 + }
  1464 + }.
1451 1465  
1452 1466  
1453 1467  
... ... @@ -1602,24 +1616,22 @@ define Result(Error,HTTP_RequestType)
1602 1616 if ls = "post" then ok(post) else
1603 1617 error(not_get_or_post_request(ls)).
1604 1618  
1605   -define Result(Error,HTTP_RequestLine)
1606   - read_request_line
1607   - (
1608   - BufferedConnection connection,
1609   - Int dead_line,
1610   - DenialOfService dos,
1611   - SState s
1612   - ) =
1613   - if read_word(connection, dead_line, dos, s) is
  1619 +public define Result(Error, HTTP_RequestLine)
  1620 + read_request_line
  1621 + (
  1622 + BufferedConnection connection
  1623 + ) =
  1624 + if read_word(connection) is
1614 1625 {
1615   - error(msg) then error(msg),
1616   - ok(get_or_post) then if read_word(connection, dead_line, dos, s) is
1617   - {
1618   - error(msg) then error(msg),
1619   - ok(uri_and_query_string) then if read_word(connection, dead_line, dos, s) is
  1626 + error(msg) then error(msg),
  1627 + ok(get_or_post) then
  1628 + if read_word(connection) is
  1629 + {
  1630 + error(msg) then error(msg),
  1631 + ok(uri_and_query_string) then if read_word(connection) is
1620 1632 {
1621   - error(msg) then error(msg),
1622   - ok(http_version) then if read_new_line(connection, dead_line, dos, s) is
  1633 + error(msg) then error(msg),
  1634 + ok(http_version) then if read_new_line(connection) is
1623 1635 {
1624 1636 error(msg) then error(msg),
1625 1637 ok(_) then if separate_uri_from_query_string(uri_and_query_string,0) is
... ... @@ -1636,10 +1648,6 @@ define Result(Error,HTTP_RequestLine)
1636 1648  
1637 1649  
1638 1650  
1639   -
1640   -
1641   -
1642   -
1643 1651 *** [4.8] Reading the HTTP headers.
1644 1652  
1645 1653 Each header is made of a name (containing only letters, the underscore, digits and the
... ... @@ -1663,34 +1671,28 @@ define Result(Error,String)
1663 1671 read_header_name
1664 1672 (
1665 1673 BufferedConnection connection,
1666   - Int dead_line,
1667   - List(Word8) so_far,
1668   - DenialOfService dos,
1669   - SState s
  1674 + List(Word8) so_far
1670 1675 ) =
1671   - if next_char(connection, dead_line, dos, s) is
  1676 + if next_char(connection) is
1672 1677 {
1673 1678 error(msg) then error(msg),
1674 1679 ok(c) then
1675 1680 if is_header_name_char(c)
1676   - then read_header_name(connection, dead_line, [to_lower(c) . so_far], dos, s)
1677   - else unput(c, s); ok(implode(reverse(so_far)))
  1681 + then read_header_name(connection, [to_lower(c) . so_far])
  1682 + else unput(c, connection); ok(implode(reverse(so_far)))
1678 1683 }.
1679 1684  
1680 1685 define Result(Error,One)
1681 1686 skip_colon
1682 1687 (
1683   - BufferedConnection connection,
1684   - Int dead_line,
1685   - DenialOfService dos,
1686   - SState s
  1688 + BufferedConnection connection
1687 1689 ) =
1688 1690 //Skip the blank char until ':'
1689   - if skip_http_blanks(connection, dead_line, dos, s) is
  1691 + if skip_http_blanks(connection) is
1690 1692 {
1691 1693 error(msg) then error(msg),
1692 1694 ok(_) then
1693   - if next_char(connection, dead_line, dos, s) is
  1695 + if next_char(connection) is
1694 1696 {
1695 1697 error(msg) then error(msg),
1696 1698 ok(c) then
... ... @@ -1701,72 +1703,66 @@ define Result(Error,One)
1701 1703  
1702 1704  
1703 1705 define Result(Error,String)
1704   - read_header_value
1705   - (
1706   - BufferedConnection connection,
1707   - Int dead_line,
1708   - List(Word8) so_far,
1709   - DenialOfService dos,
1710   - SState s
1711   - ) =
1712   - if next_char(connection, dead_line, dos, s) is
  1706 + read_header_value
  1707 + (
  1708 + BufferedConnection connection,
  1709 + List(Word8) so_far
  1710 + ) =
  1711 + if next_char(connection) is
1713 1712 {
1714 1713 error(msg) then error(msg),
1715 1714 ok(c) then
1716 1715 if c = 13
1717   - then if next_char(connection, dead_line, dos, s) is
  1716 + then if next_char(connection) is
1718 1717 {
1719 1718 error(msg) then error(msg),
1720 1719 ok(d) then
1721 1720 if d = 10
1722   - then if next_char(connection, dead_line, dos, s) is
  1721 + then if next_char(connection) is
1723 1722 {
1724 1723 error(msg) then error(msg),
1725 1724 ok(e) then
1726 1725 if is_strict_blank(e)
1727   - then read_header_value(connection,dead_line, [e . so_far], dos, s)
1728   - else (unput(e, s); ok(implode(reverse(so_far))))
  1726 + then read_header_value(connection, [e . so_far])
  1727 + else (unput(e, connection); ok(implode(reverse(so_far))))
1729 1728 }
1730   - else read_header_value(connection,dead_line,[d, c . so_far],dos, s)
  1729 + else read_header_value(connection,[d, c . so_far])
1731 1730 }
1732   - else read_header_value(connection,dead_line,[c . so_far],dos, s)
  1731 + else read_header_value(connection,[c . so_far])
1733 1732 }.
1734 1733  
1735 1734  
1736 1735 Reading a single header.
1737 1736  
1738 1737 define Result(Error,Maybe(HTTP_header))
1739   - read_header
1740   - (
1741   - BufferedConnection connection,
1742   - Int dead_line,
1743   - DenialOfService dos,
1744   - SState s
1745   - ) =
  1738 + read_header
  1739 + (
  1740 + BufferedConnection connection
  1741 + ) =
1746 1742 //Find the name
1747   - if read_header_name(connection, dead_line, [], dos, s) is
  1743 + if read_header_name(connection, []) is
1748 1744 {
1749 1745 error(msg) then error(msg),
1750 1746 ok(name) then
1751 1747 if name = "" then
1752   - if read_and_ignore(connection, dead_line, 2, dos, s) /* 13 and 10 */ is
  1748 + if read_and_ignore(connection, 2) /* 13 and 10 */ is
1753 1749 {
1754 1750 error(msg) then error(msg),
1755 1751 ok(_) then // this is the blank line
1756 1752 ok(failure) // end of headers
1757 1753 }
1758 1754 //skip the ':' and blank before and after it
1759   - else if skip_colon(connection, dead_line, dos, s) is
  1755 + else if skip_colon(connection) is
1760 1756 {
1761 1757 error(msg) then error(msg),
1762 1758 ok(_) then
1763 1759 //skip the blank char after the ':'
1764   - if skip_http_blanks(connection, dead_line, dos, s) is
  1760 + if skip_http_blanks(connection) is
1765 1761 {
1766 1762 error(msg) then error(msg),
1767 1763 ok(_) then
1768 1764 //Now read the value
1769   - if read_header_value(connection, dead_line, [], dos, s) is
  1765 + if read_header_value(connection, []) is
1770 1766 {
1771 1767 error(msg) then error(msg),
1772 1768 ok(value) then ok(success(http_header(name,value)))
... ... @@ -1779,22 +1775,19 @@ define Result(Error,Maybe(HTTP_header))
1779 1775  
1780 1776 Reading all the headers.
1781 1777  
1782   -define Result(Error,List(HTTP_header))
  1778 +public define Result(Error,List(HTTP_header))
1783 1779 read_http_headers
1784 1780 (
1785   - BufferedConnection connection,
1786   - Int dead_line,
1787   - DenialOfService dos,
1788   - SState s
  1781 + BufferedConnection connection
1789 1782 ) =
1790   - if read_header(connection, dead_line, dos, s) is
  1783 + if read_header(connection) is
1791 1784 {
1792 1785 error(msg) then error(msg),
1793 1786 ok(mbh) then if mbh is
1794 1787 {
1795 1788 failure then ok([ ]),
1796 1789 success(header) then
1797   - if read_http_headers(connection, dead_line, dos, s) is
  1790 + if read_http_headers(connection) is
1798 1791 {
1799 1792 error(msg) then error(msg),
1800 1793 ok(others) then ok([header . others])
... ... @@ -1813,7 +1806,7 @@ define Result(Error,List(HTTP_header))
1813 1806 The size of the body of the request is given under the 'Content-Length' header. If this
1814 1807 header is not present, the size is assumed to be zero.
1815 1808  
1816   -define Result(Error,Int)
  1809 +public define Result(Error,Int)
1817 1810 get_body_size
1818 1811 (
1819 1812 List(HTTP_header) headers
... ... @@ -1843,7 +1836,7 @@ define Result(Error,Int)
1843 1836 may be broken. In that case, we must not try to read indefinitely. On the contrary, we
1844 1837 make at most 10 retries, with a small sleeping time between any two of them.
1845 1838  
1846   -define Result(Error, ByteArray)
  1839 +public define Result(Error, ByteArray)
1847 1840 read_http_body
1848 1841 (
1849 1842 BufferedConnection connection,
... ... @@ -3183,12 +3176,12 @@ define One
3183 3176 //println("Request time: " + format_http_date(start_time));
3184 3177 if dos is denial_of_service(mc_v,rld_v,hd_v,ad_v,ld_v,ra_v) then
3185 3178 if remote_IP_address_and_port(connection.conn) is (ip_addr,port) then
3186   - if read_request_line(connection, start_time+*rld_v, dos, s) is
  3179 + if read_request_line(connection) is
3187 3180 {
3188 3181 error(msg) then print(format(msg)),
3189 3182 ok(rqline) then //request line
3190 3183 //print_delta("read_request_line");
3191   - if read_http_headers(connection, start_time+*hd_v, dos, s) is
  3184 + if read_http_headers(connection) is
3192 3185 {
3193 3186 error(msg) then print(format(msg)),
3194 3187 ok(headers) then //print_delta("read_http_headers");
... ... @@ -3237,7 +3230,7 @@ define One
3237 3230 success(target) then
3238 3231  
3239 3232 //get the content of the current buffer and unput char list
3240   - with buffer = get_and_erase_buffer(connection, s),
  3233 + with buffer = get_and_erase_buffer(connection),
3241 3234 buffer_size = length(buffer),
3242 3235 //println("buffer Size = "+buffer_size);
3243 3236 //println("Old body size "+body_size+" New body size request = "+body_size - buffer_size);
... ... @@ -3295,8 +3288,8 @@ define Server -&gt; ((RWStream) -&gt; One)
3295 3288 if is_dubious_IP(addr,dos)
3296 3289 then print("Rejecting dubious IP address "+ip_addr_to_string(addr)+"\n")
3297 3290 else
3298   - with connection = buffered_connection(tcp(conn), var(constant_byte_array(0, 0)), var(0)),
3299   - http_https_handler(sites, connection, false, dos, sstate(var([]),var(0),var(0))).
  3291 + with connection = buffered_connection(tcp(conn), var(constant_byte_array(0, 0)), var(0), var([])),
  3292 + http_https_handler(sites, connection, false, dos, sstate(var(0),var(0))).
3300 3293 public define One
3301 3294 http_direct_handler
3302 3295 (
... ... @@ -3308,8 +3301,8 @@ public define One
3308 3301 if is_dubious_IP(addr,dos)
3309 3302 then print("Rejecting dubious IP address "+ip_addr_to_string(addr)+"\n")
3310 3303 else
3311   - with connection = buffered_connection(tcp(conn), var(constant_byte_array(0, 0)), var(0)),
3312   - http_https_handler(sites, connection, false, dos, sstate(var([]),var(0),var(0))).
  3304 + with connection = buffered_connection(tcp(conn), var(constant_byte_array(0, 0)), var(0), var([])),
  3305 + http_https_handler(sites, connection, false, dos, sstate(var(0),var(0))).
3313 3306  
3314 3307  
3315 3308 define Server -> (SSL_Connection -> One)
... ... @@ -3319,8 +3312,8 @@ define Server -&gt; (SSL_Connection -&gt; One)
3319 3312 DenialOfService dos
3320 3313 ) =
3321 3314 (Server server) |-> (SSL_Connection conn) |->
3322   - with connection = buffered_connection(ssl(conn), var(constant_byte_array(0, 0)), var(0)),
3323   - http_https_handler(sites, connection, true, dos, sstate(var([]),var(0),var(0))).
  3315 + with connection = buffered_connection(ssl(conn), var(constant_byte_array(0, 0)), var(0), var([])),
  3316 + http_https_handler(sites, connection, true, dos, sstate(var(0),var(0))).
3324 3317  
3325 3318  
3326 3319  
... ... @@ -3712,12 +3705,12 @@ define Server -&gt; ((RWStream) -&gt; One)
3712 3705 ) =
3713 3706 (Server server) |-> (RWStream conn) |->
3714 3707 with start_time = (Int)now,
3715   - connection = buffered_connection(tcp(conn), var(constant_byte_array(0, 0)), var(0)),
3716   - if read_request_line(connection, start_time+*request_line_delay(dos), dos, ss) is
  3708 + connection = buffered_connection(tcp(conn), var(constant_byte_array(0, 0)), var(0), var([])),
  3709 + if read_request_line(connection) is
3717 3710 {
3718 3711 error(msg) then print(format(msg)),
3719 3712 ok(request_line) then
3720   - if read_http_headers(connection, start_time+*headers_delay(dos), dos, ss) is
  3713 + if read_http_headers(connection) is
3721 3714 {
3722 3715 error(msg) then print(format(msg)),
3723 3716 ok(headers) then if get_host_header_value(headers) is
... ...
web/CXM_xml_rpc.anubis
1   -๏ปฟ/*
2   - * Created by PyramIDE.
3   - * User: Totoro
4   - * Date: 29/06/2013
5   - * Time: 00:47
6   - *
7   - * To change this template use Tools | Options | Coding | Edit Standard Headers.
8   - */
9   -
10   -read tools/base64.anubis
11   -read tools/basis.anubis
12   -read tools/connections.anubis
13   -read system/convert.anubis
14   -read system/string.anubis
15   -read web/CXM_common.anubis
16   -read web/CXM_http_get_common.anubis
17   -read web/CXM_xml_rpc_parser.anubis
18   -read web/CXM_xml_rpc_types.anubis
19   -
20   -
21   -define XML_RPC_parameters sysinfo_params =
22   - parameters
23   - [
24   - parameter[int(1)],
25   - parameter[bool(true)],
26   - parameter[string("This is a string")],
27   - parameter[double(1.45)],
28   - parameter[datetime("date to do")],
29   - parameter[base64("Base 64 content")],
30   - parameter[struct(members([
31   - member("1st member", int(2)),
32   - member("2nd member", string("this is the 2nd string"))
33   - ]))],
34   - parameter[array(array([
35   - int(3),
36   - string("3rd string")
37   - ]))]
38   - ].
39   -
40   -define XML_RPC_parameters empty_param = parameters [].
41   -
42   -public type XML_RPC_Result:
43   - cannot_resolve_server_name(DNS_Result),
44   - cannot_connect_to_server(NetworkConnectError),
45   - transmission_problem,
46   - request_refused_by_server,
47   - ok(String response, // HTTP response line from the server
48   - List(HTTP_header) headers, // HTTP headers received from the server
49   - String document). // The HTML document itself
50   -
51   -public type XML_RPC_Auth:
52   - none,
53   - basic(String login, String password).
54   -
55   -public type XML_RPC_client:
56   - xml_rpc_client(
57   - Connection conn,
58   - XML_RPC_Auth auth,
59   - String url,
60   - String user_agent,
61   - String host).
62   -
63   -define String
64   - tab
65   - (
66   - Int position
67   - )=
68   - to_string(constant_byte_array(position * 2, ' ')).
69   -
70   -define String format_struct(XML_RPC_struct structure, Int position).
71   -define String format_array(XML_RPC_array array, Int position).
72   -
73   -define String format_int_value ( Word32 value) = "<value><i4>"+to_String(value)+"</i4></value>" + crlf.
74   -define String format_boolean_value ( Bool value) = "<value><boolean>"+to_String_value(value)+"</boolean></value>" + crlf.
75   -define String format_string_value ( String value) = "<value><string>"+value+"</string></value>" + crlf.
76   -define String format_double_value ( Float value) = "<value><double>"+float_to_string(value, 10)+"</double></value>" + crlf.
77   -define String format_datetime_value ( String value) = "<value><dateTime.iso8601>"+value+"</dateTime.iso8601></value>" + crlf.
78   -define String format_base64_value ( String value) = "<value><base64>"+value+"</base64></value>" + crlf.
79   -
80   -define String
81   - format_value
82   - (
83   - XML_RPC_value rpc_value,
84   - Int position
85   - )=
86   - with return = if rpc_value is
87   - {
88   - int(value) then format_int_value(value),
89   - bool(value) then format_boolean_value(value),
90   - string(value) then format_string_value(value),
91   - double(value) then format_double_value(value),
92   - datetime(value) then format_datetime_value(value),
93   - base64(value) then format_base64_value(value),
94   - struct(value) then format_struct(value, position + 1),
95   - array(value) then format_array(value, position + 1)
96   - },
97   - tab(position) + return.
98   -
99   -
100   -define String
101   - _format_struct
102   - (
103   - String so_far,
104   - List(XML_RPC_struct_member) members,
105   - Int position
106   - )=
107   - if members is
108   - {
109   - [] then so_far,
110   - [h . t] then
111   - if h is member(name, val) then
112   - _format_struct( so_far + tab(position) + "<member>" + crlf +
113   - tab(position + 1)+"<name>"+name+"</name>" + crlf +
114   - format_value(val, position + 1) +
115   - tab(position + 1) + "</member>" + crlf,
116   - t,
117   - position)
118   - }.
119   -
120   -define String
121   - format_struct
122   - (
123   - XML_RPC_struct struct,
124   - Int position
125   - ) =
126   - if struct is members(structure_members) then
127   - /*tab(position) +*/ "<struct>" + crlf +
128   - _format_struct("", structure_members, position+1)+
129   - tab(position + 1) + "</struct>" + crlf.
130   -
131   -define String
132   - _format_array
133   - (
134   - String so_far,
135   - List(XML_RPC_value) values,
136   - Int position
137   - )=
138   - if values is
139   - {
140   - [] then so_far,
141   - [h . t] then _format_array( so_far + format_value(h, position), t, position)
142   - }.
143   -
144   -define String
145   - format_array
146   - (
147   - XML_RPC_array arr,
148   - Int position
149   - )
150   - =
151   - if arr is array(values) then
152   - /*tab(position) +*/ "<array>" + crlf +
153   - tab(position + 1) + "<data>" + crlf+
154   - _format_array("", values, position + 2)+
155   - tab(position+2)+"</data>" + crlf +
156   - tab(position + 1) + "</array>" + crlf.
157   -
158   -public define String
159   - format_xml_rpc_values
160   - (
161   - List(XML_RPC_value) values,
162   - Int position,
163   - String so_far
164   - )=
165   - if values is
166   - {
167   - [] then so_far,
168   - [ h . t ] then
169   - format_xml_rpc_values(t, position, so_far + format_value(h, position))
170   - }.
171   -
172   -public define String
173   - format_xml_rpc_parameter
174   - (
175   - XML_RPC_parameter param,
176   - Int position
177   - )=
178   - if param is parameter(values) then
179   - format_xml_rpc_values(values, position, "")
180   - .
181   -
182   -
183   -define String
184   - _format_xml_rpc_parameters
185   - (
186   - String so_far,
187   - List(XML_RPC_parameter) params,
188   - Int position
189   - )=
190   - if params is
191   - {
192   - [] then so_far,
193   - [ h . t ] then
194   - _format_xml_rpc_parameters( so_far + tab(position) + "<param>" + crlf +
195   - format_xml_rpc_parameter(h, position + 1) +
196   - tab(position+1) + "</param>" + crlf,
197   - t,
198   - position)
199   - }.
200   -
201   -public define String
202   - format_xml_rpc_parameters
203   - (
204   - XML_RPC_parameters params,
205   - Int position
206   - )=
207   - if params is parameters(list_param) then
208   - tab(position)+"<params>" + crlf +
209   - _format_xml_rpc_parameters("", list_param, position+1) +
210   - tab(position+1)+"</params>".
211   -
212   -public define String
213   - format_xml_rpc_fault
214   - (
215   - XML_RPC_value value,
216   - Int position
217   - )=
218   - tab(position)+"<fault>" + crlf +
219   - format_value(value, position+1) +
220   - tab(position+1)+"</fault>".
221   -
222   -public define Bool
223   - accept_policy
224   - (
225   - Maybe(X509) suspect_certificate
226   - ) = true.
227   -
228   -public define Maybe(XML_RPC_client)
229   - xml_rpc_new_client
230   - (
231   - String server_name,
232   - Bool use_ssl,
233   - XML_RPC_Auth auth,
234   - String user_agent,
235   - String host
236   - )=
237   - if separate_name_port(server_name, if use_ssl then 443 else 80) is (name, server_port) then
238   - //
239   - // resolve server name and call 'https_get' with numeric server address:
240   - //
241   - with a = dns(name),
242   - if a is ok(server_addr) then
243   - //connect to server with right protocol
244   - if use_ssl then
245   - println("SSL "+server_port+ " "+server_name);
246   - if open_SSL_connection(server_name, server_addr, server_port, accept_policy) is
247   - {
248   - error(msg) then failure,
249   - ok(conn) then success(xml_rpc_client(ssl(conn), auth, server_name, user_agent, host))
250   - }
251   - else
252   - println("TCP "+server_port+ " "+server_name);
253   - if (Result(NetworkConnectError,RWStream))connect(server_addr, server_port) is
254   - {
255   - error(e) then failure,
256   - ok(conn) then success(xml_rpc_client(tcp(conn), auth, server_name, user_agent, host))
257   - }
258   - else
259   - failure.
260   -
261   -define Maybe(XML_RPC_response)
262   - receive
263   - (
264   - Bool print_dump,
265   - Connection conn
266   - )=
267   - //TODO find the header and content-lenght to get full length of answer
268   -
269   - if read(conn, 16384, 5) is
270   - {
271   - error then println("Read error");failure,
272   - timeout then println("Read timeout");failure,
273   - ok(ba) then
274   - with xml_response = to_string(ba),
275   - typed_response = xml_rpc_get_response(xml_response),
276   - (if print_dump then
277   -
278   - println("=== Server answer ==="+crlf + xml_response );
279   - println("=== XML_RPC Anubis interpretation ===");
280   -
281   - if typed_response is
282   - {
283   - failure then println("Interpretation error"),
284   - success(result) then
285   - if result is
286   - {
287   - ok(ok_res) then println(format_xml_rpc_parameters(ok_res,1)),
288   - fault(fault) then println(format_xml_rpc_fault(fault,1))
289   - }
290   -
291   - }
292   - else unique);
293   - typed_response
294   - }
295   - .
296   -
297   -public define Maybe(XML_RPC_response)
298   - xml_rpc_client_execute
299   - (
300   - Bool print_dump,
301   - XML_RPC_client client,
302   - String url,
303   - String method_name,
304   - XML_RPC_parameters params
305   - //(XML-string)->$T answer_handler //convert the xml answer to anubis type
306   - )=
307   - if client is xml_rpc_client(conn, auth, server_name, user_agent, host) then
308   - //execute the method on remote server
309   - // - 1 - Format the xml body to comply with XML RPC
310   - with body = "<?xml version=\"1.0\"?>" + crlf +
311   - tab(1)+"<methodCall>" + crlf +
312   - tab(2)+"<methodName>" + method_name +"</methodName>" + crlf +
313   - format_xml_rpc_parameters(params, 2) +
314   - tab(1)+"</methodCall>",
315   -
316   - // - 2 - Format the POST HTTP request
317   - with request = "POST "+url+" HTTP/1.1"+ crlf + //HTTP/1.1 is very important because it allow to send multiple execute
318   - "User-Agent: "+ user_agent + crlf + //with only one connection (keep-alive is default in http 1.1)
319   - "Host: " + server_name + crlf +
320   - "Content-type: text/xml" + crlf +
321   - if auth is
322   - {
323   - none then "",
324   - basic(login, pass) then "Authorization: Basic "+base64_encode(login+":"+pass)+ crlf
325   - }+
326   - "Content-length: " + length(body)+ crlf +
327   -
328   - //format_headers(headers) +
329   - crlf +
330   - body,
331   -
332   - // - 3 - send it to remote
333   -
334   - //
335   - // Send the HTTP request, and receive the answer:
336   - //
337   - (if print_dump then
338   - (
339   - print("----- request ----\n");
340   - print(request);
341   - print("\n")
342   - ) else unique);
343   -
344   - if write(conn, to_byte_array(request)) is
345   - {
346   - failure then failure,
347   - success(_) then receive(print_dump, conn)
348   - }.
349   -
350   - //wait the answer
351   -
352   -
353   -global define One
354   - xml_rpc_test
355   - (
356   - List(String) args
357   - )=
358   - if xml_rpc_new_client("mail.calexium.com:33610", true, basic("admin","the secret passsword"), "Anubis XML-RPC", "127.0.0.1") is
359   - {
360   - failure then println(" xml_rpc_test new client failure"),
361   - success(rpc_client) then
362   - forget(xml_rpc_client_execute(true, rpc_client, "/Settings", "list_domains", empty_param))
363   - //forget(xml_rpc_client_execute(true, rpc_client, "/Settings", "delete_domain", parameters([parameter[string("amisdefontainebleau.org")]])))
364   - //forget(xml_rpc_client_execute(true, rpc_client, "/Settings", "create_domain", empty_param))
365   - }.
366   -
  1 +๏ปฟ/*
  2 + * Created by PyramIDE.
  3 + * User: Totoro
  4 + * Date: 29/06/2013
  5 + * Time: 00:47
  6 + *
  7 + */
  8 +
  9 +read tools/base64.anubis
  10 +transmit tools/basis.anubis
  11 +read tools/connections.anubis
  12 +read system/convert.anubis
  13 +transmit system/string.anubis
  14 +read calexium_lib/web/CXM_common.anubis
  15 +read calexium_lib/web/CXM_http_get_common.anubis
  16 +read calexium_lib/web/CXM_multihost_http_server.anubis
  17 +transmit calexium_lib/web/CXM_xml_rpc_parser.anubis
  18 +transmit calexium_lib/web/CXM_xml_rpc_types.anubis
  19 +
  20 +
  21 +define XML_RPC_parameters sysinfo_params =
  22 + parameters
  23 + [
  24 + parameter[int(1)],
  25 + parameter[bool(true)],
  26 + parameter[string("This is a string")],
  27 + parameter[double(1.45)],
  28 + parameter[datetime("date to do")],
  29 + parameter[base64("Base 64 content")],
  30 + parameter[struct(members([
  31 + member("1st member", int(2)),
  32 + member("2nd member", string("this is the 2nd string"))
  33 + ]))],
  34 + parameter[array(array([
  35 + int(3),
  36 + string("3rd string")
  37 + ]))]
  38 + ].
  39 +
  40 +define XML_RPC_parameters empty_param = parameters [].
  41 +
  42 +public type XML_RPC_Result:
  43 + cannot_resolve_server_name(DNS_Result),
  44 + cannot_connect_to_server(NetworkConnectError),
  45 + transmission_problem,
  46 + request_refused_by_server,
  47 + ok(String response, // HTTP response line from the server
  48 + List(HTTP_header) headers, // HTTP headers received from the server
  49 + String document). // The HTML document itself
  50 +
  51 +public type XML_RPC_Auth:
  52 + none,
  53 + basic(String login, String password).
  54 +
  55 +public type XML_RPC_client:
  56 + xml_rpc_client(
  57 + Connection conn,
  58 + XML_RPC_Auth auth,
  59 + String url,
  60 + String user_agent,
  61 + String host).
  62 +
  63 +define String
  64 + tab
  65 + (
  66 + Int position
  67 + )=
  68 + to_string(constant_byte_array(position * 2, ' ')).
  69 +
  70 +define String format_struct(XML_RPC_struct structure, Int position).
  71 +define String format_array(XML_RPC_array array, Int position).
  72 +
  73 +define String format_int_value ( Word32 value) = "<value><i4>"+to_String(value)+"</i4></value>" + crlf.
  74 +define String format_boolean_value ( Bool value) = "<value><boolean>"+to_String_value(value)+"</boolean></value>" + crlf.
  75 +define String format_string_value ( String value) = "<value><string>"+value+"</string></value>" + crlf.
  76 +define String format_double_value ( Float value) = "<value><double>"+float_to_string(value, 10)+"</double></value>" + crlf.
  77 +define String format_datetime_value ( String value) = "<value><dateTime.iso8601>"+value+"</dateTime.iso8601></value>" + crlf.
  78 +define String format_base64_value ( String value) = "<value><base64>"+value+"</base64></value>" + crlf.
  79 +
  80 +define String
  81 + format_value
  82 + (
  83 + XML_RPC_value rpc_value,
  84 + Int position
  85 + )=
  86 + with return = if rpc_value is
  87 + {
  88 + int(value) then format_int_value(value),
  89 + bool(value) then format_boolean_value(value),
  90 + string(value) then format_string_value(value),
  91 + double(value) then format_double_value(value),
  92 + datetime(value) then format_datetime_value(value),
  93 + base64(value) then format_base64_value(value),
  94 + struct(value) then format_struct(value, position + 1),
  95 + array(value) then format_array(value, position + 1)
  96 + },
  97 + tab(position) + return.
  98 +
  99 +
  100 +define String
  101 + _format_struct
  102 + (
  103 + String so_far,
  104 + List(XML_RPC_struct_member) members,
  105 + Int position
  106 + )=
  107 + if members is
  108 + {
  109 + [] then so_far,
  110 + [h . t] then
  111 + if h is member(name, val) then
  112 + _format_struct( so_far + tab(position) + "<member>" + crlf +
  113 + tab(position + 1)+"<name>"+name+"</name>" + crlf +
  114 + format_value(val, position + 1) +
  115 + tab(position + 1) + "</member>" + crlf,
  116 + t,
  117 + position)
  118 + }.
  119 +
  120 +define String
  121 + format_struct
  122 + (
  123 + XML_RPC_struct struct,
  124 + Int position
  125 + ) =
  126 + if struct is members(structure_members) then
  127 + /*tab(position) +*/ "<struct>" + crlf +
  128 + _format_struct("", structure_members, position+1)+
  129 + tab(position + 1) + "</struct>" + crlf.
  130 +
  131 +define String
  132 + _format_array
  133 + (
  134 + String so_far,
  135 + List(XML_RPC_value) values,
  136 + Int position
  137 + )=
  138 + if values is
  139 + {
  140 + [] then so_far,
  141 + [h . t] then _format_array( so_far + format_value(h, position), t, position)
  142 + }.
  143 +
  144 +define String
  145 + format_array
  146 + (
  147 + XML_RPC_array arr,
  148 + Int position
  149 + )
  150 + =
  151 + if arr is array(values) then
  152 + /*tab(position) +*/ "<array>" + crlf +
  153 + tab(position + 1) + "<data>" + crlf+
  154 + _format_array("", values, position + 2)+
  155 + tab(position+2)+"</data>" + crlf +
  156 + tab(position + 1) + "</array>" + crlf.
  157 +
  158 +public define String
  159 + format_xml_rpc_values
  160 + (
  161 + List(XML_RPC_value) values,
  162 + Int position,
  163 + String so_far
  164 + )=
  165 + if values is
  166 + {
  167 + [] then so_far,
  168 + [ h . t ] then
  169 + format_xml_rpc_values(t, position, so_far + format_value(h, position))
  170 + }.
  171 +
  172 +public define String
  173 + format_xml_rpc_parameter
  174 + (
  175 + XML_RPC_parameter param,
  176 + Int position
  177 + )=
  178 + if param is parameter(values) then
  179 + format_xml_rpc_values(values, position, "")
  180 + .
  181 +
  182 +
  183 +define String
  184 + _format_xml_rpc_parameters
  185 + (
  186 + String so_far,
  187 + List(XML_RPC_parameter) params,
  188 + Int position
  189 + )=
  190 + if params is
  191 + {
  192 + [] then so_far,
  193 + [ h . t ] then
  194 + _format_xml_rpc_parameters( so_far + tab(position) + "<param>" + crlf +
  195 + format_xml_rpc_parameter(h, position + 1) +
  196 + tab(position+1) + "</param>" + crlf,
  197 + t,
  198 + position)
  199 + }.
  200 +
  201 +public define String
  202 + format_xml_rpc_parameters
  203 + (
  204 + XML_RPC_parameters params,
  205 + Int position
  206 + )=
  207 + if params is parameters(list_param) then
  208 + tab(position)+"<params>" + crlf +
  209 + _format_xml_rpc_parameters("", list_param, position+1) +
  210 + tab(position+1)+"</params>".
  211 +
  212 +public define String
  213 + format_xml_rpc_fault
  214 + (
  215 + XML_RPC_value value,
  216 + Int position
  217 + )=
  218 + tab(position)+"<fault>" + crlf +
  219 + format_value(value, position+1) +
  220 + tab(position+1)+"</fault>".
  221 +
  222 +public define Bool
  223 + accept_policy
  224 + (
  225 + Maybe(X509) suspect_certificate
  226 + ) = true.
  227 +
  228 +public define Maybe(XML_RPC_client)
  229 + xml_rpc_new_client
  230 + (
  231 + String server_name,
  232 + Bool use_ssl,
  233 + XML_RPC_Auth auth,
  234 + String user_agent,
  235 + String host
  236 + )=
  237 + if separate_name_port(server_name, if use_ssl then 443 else 80) is (name, server_port) then
  238 + //
  239 + // resolve server name and call 'https_get' with numeric server address:
  240 + //
  241 + with a = dns(name),
  242 + if a is ok(server_addr) then
  243 + //connect to server with right protocol
  244 + if use_ssl then
  245 + println("SSL "+server_port+ " "+server_name);
  246 + if open_SSL_connection(server_name, server_addr, server_port, accept_policy) is
  247 + {
  248 + error(msg) then failure,
  249 + ok(conn) then success(xml_rpc_client(ssl(conn), auth, server_name, user_agent, host))
  250 + }
  251 + else
  252 + println("TCP "+server_port+ " "+server_name);
  253 + if (Result(NetworkConnectError,RWStream))connect(server_addr, server_port) is
  254 + {
  255 + error(e) then failure,
  256 + ok(conn) then success(xml_rpc_client(tcp(conn), auth, server_name, user_agent, host))
  257 + }
  258 + else
  259 + failure.
  260 +define Maybe(XML_RPC_response)
  261 + receive
  262 + (
  263 + Bool print_dump,
  264 + Connection conn
  265 + )=
  266 + //TODO find the header and content-lenght to get full length of answer
  267 +
  268 + if read(conn, 16384, 5) is
  269 + {
  270 + error then println("Read error");failure,
  271 + timeout then println("Read timeout");failure,
  272 + ok(ba) then
  273 + with xml_response = to_string(ba),
  274 + typed_response = xml_rpc_get_response(xml_response),
  275 + (if print_dump then
  276 +
  277 + println("=== Server answer ==="+crlf + xml_response );
  278 + println("=== XML_RPC Anubis interpretation ===");
  279 +
  280 + if typed_response is
  281 + {
  282 + failure then println("Interpretation error"),
  283 + success(result) then
  284 + if result is
  285 + {
  286 + ok(ok_res) then println(format_xml_rpc_parameters(ok_res,1)),
  287 + fault(fault) then println(format_xml_rpc_fault(fault,1))
  288 + }
  289 +
  290 + }
  291 + else unique);
  292 + typed_response
  293 + }
  294 + .
  295 +
  296 +define Maybe(XML_RPC_response)
  297 + receive_new
  298 + (
  299 + Bool print_dump,
  300 + Connection conn
  301 + )=
  302 + //TODO find the header and content-lenght to get full length of answer
  303 + //construct a buffered connection
  304 + with b_con = buffered_connection(conn),
  305 + if skip_line(b_con) is
  306 + {
  307 + error(msg) then print(format(msg));failure,
  308 + ok(_) then
  309 + if read_http_headers(b_con) is
  310 + {
  311 + error(msg) then print(format(msg));failure,
  312 + ok(headers) then
  313 + if get_body_size(headers) is
  314 + {
  315 + error(msg) then print(format(msg));failure,
  316 + ok(body_size) then
  317 + if read_http_body(b_con, body_size, constant_byte_array(0,0), 1000) is
  318 + {
  319 + error(msg) then print(format(msg));failure,
  320 + ok(body) then
  321 + with xml_response = to_string(body),
  322 + with typed_response = xml_rpc_get_response(xml_response),
  323 + (if print_dump then
  324 +
  325 + println("=== Server answer ==="+crlf + xml_response);
  326 + println("=== XML_RPC Anubis interpretation ===");
  327 +
  328 + if typed_response is
  329 + {
  330 + failure then println("Interpretation error"),
  331 + success(result) then
  332 + if result is
  333 + {
  334 + ok(ok_res) then println(format_xml_rpc_parameters(ok_res,1)),
  335 + fault(fault) then println(format_xml_rpc_fault(fault,1))
  336 + }
  337 +
  338 + }
  339 + else unique);
  340 + typed_response
  341 + }
  342 + }
  343 + }}
  344 + .
  345 +
  346 +public define Maybe(XML_RPC_response)
  347 + xml_rpc_client_execute
  348 + (
  349 + Bool print_dump,
  350 + XML_RPC_client client,
  351 + String url,
  352 + String method_name,
  353 + XML_RPC_parameters params
  354 + //(XML-string)->$T answer_handler //convert the xml answer to anubis type
  355 + )=
  356 + if client is xml_rpc_client(conn, auth, server_name, user_agent, host) then
  357 + //execute the method on remote server
  358 + // - 1 - Format the xml body to comply with XML RPC
  359 + with body = "<?xml version=\"1.0\"?>" + crlf +
  360 + tab(1)+"<methodCall>" + crlf +
  361 + tab(2)+"<methodName>" + method_name +"</methodName>" + crlf +
  362 + format_xml_rpc_parameters(params, 2) +
  363 + tab(1)+"</methodCall>",
  364 +
  365 + // - 2 - Format the POST HTTP request
  366 + with request = "POST "+url+" HTTP/1.1"+ crlf + //HTTP/1.1 is very important because it allow to send multiple execute
  367 + "User-Agent: "+ user_agent + crlf + //with only one connection (keep-alive is default in http 1.1)
  368 + "Host: " + server_name + crlf +
  369 + "Content-type: text/xml" + crlf +
  370 + if auth is
  371 + {
  372 + none then "",
  373 + basic(login, pass) then "Authorization: Basic "+base64_encode(login+":"+pass)+ crlf
  374 + }+
  375 + "Content-length: " + length(body)+ crlf +
  376 +
  377 + //format_headers(headers) +
  378 + crlf +
  379 + body,
  380 +
  381 + // - 3 - send it to remote
  382 +
  383 + //
  384 + // Send the HTTP request, and receive the answer:
  385 + //
  386 + (if print_dump then
  387 + (
  388 + print("----- request ----\n");
  389 + print(request);
  390 + print("\n")
  391 + ) else unique);
  392 +
  393 + if write(conn, to_byte_array(request)) is
  394 + {
  395 + failure then failure,
  396 + success(_) then receive_new(print_dump, conn)
  397 + }.
  398 +
  399 + //wait the answer
  400 +
  401 +
  402 +global define One
  403 + xml_rpc_test
  404 + (
  405 + List(String) args
  406 + )=
  407 + if xml_rpc_new_client("mail.calexium.com:33610", true, basic("admin","the secret passsword"), "Anubis XML-RPC", "127.0.0.1") is
  408 + {
  409 + failure then println(" xml_rpc_test new client failure"),
  410 + success(rpc_client) then
  411 + forget(xml_rpc_client_execute(false, rpc_client, "/Settings", "list_domains", empty_param))
  412 + //forget(xml_rpc_client_execute(true, rpc_client, "/Settings", "delete_domain", parameters([parameter[string("amisdefontainebleau.org")]])))
  413 + //forget(xml_rpc_client_execute(true, rpc_client, "/Settings", "create_domain", empty_param))
  414 + }.
  415 +
... ...
web/CXM_xml_rpc_parser.anubis
1   -๏ปฟ/*
2   - * Created by PyramIDE.
3   - * User: Totoro
4   - * Date: 06/07/2013
5   - * Time: 01:13
6   - *
7   - * To change this template use Tools | Options | Coding | Edit Standard Headers.
8   - */
9   -
10   -read web/CXM_xml_rpc_types.anubis
11   -read tools/streams.anubis
12   -read tools/basis.anubis
13   -read system/string.anubis
14   -read system/convert.anubis
15   -
16   -type XML_RPC_Token:
17   - none,
18   - token(String token).
19   -
20   -define Maybe(XML_RPC_value) read_value(Stream stream).
21   -
22   -define XML_RPC_Token
23   - _next_xml_token
24   - (
25   - Stream stream,
26   - List(Word8) so_far,
27   - Bool in_token
28   - )=
29   - if read_byte(stream) is
30   - {
31   - failure then none, //can't read on stream !!
32   - success(b) then
33   - //println("["+implode([b])+"]");
34   - if in_token then
35   - if b = '>' then //just found the end of bracket, so we return the token in LOWER case
36   - with tok = to_lower(implode(reverse(so_far))),
37   - //println("found tag "+tok);
38   - token(tok)
39   - else
40   - _next_xml_token(stream, [b . so_far], in_token)
41   - else
42   - if b = '<' then //just found the begin of token
43   - _next_xml_token(stream, [], true)
44   - else
45   - _next_xml_token(stream, so_far, in_token)
46   - }
47   - .
48   -
49   -
50   -
51   -define XML_RPC_Token
52   - next_xml_token
53   - (
54   - Stream stream
55   - )= _next_xml_token(stream, [], false).
56   -
57   -define Maybe(String)
58   - _xml_tag_content
59   - (
60   - Stream stream,
61   - String tag, //tag to match
62   - List(Word8) so_far,
63   - List(Word8) content,
64   - Bool in_first_token,
65   - Bool in_content,
66   - Bool in_last_token
67   -
68   - )=
69   - if read_byte(stream) is
70   - {
71   - failure then failure, //can't read on stream !!
72   - success(b) then
73   - if in_first_token then
74   - if b = '>' then //just found the end of bracket, so we return the token in LOWER case
75   - if to_lower(implode(reverse(so_far))) = tag then
76   - _xml_tag_content(stream, tag, [], [], false, true, false)
77   - else
78   - failure
79   - else
80   - _xml_tag_content(stream, tag, [b . so_far], content, in_first_token, in_content, in_last_token)
81   - else if in_content then
82   - if b = '<' then //just found the begin bracket,
83   - if read_byte(stream) is
84   - {
85   - failure then failure, //can't read on stream !!
86   - success(b) then
87   - if b = '/' then //can't find / => syntax error
88   - _xml_tag_content(stream, tag, [], content, false, false, true)
89   - else
90   - failure
91   - }
92   - else
93   - _xml_tag_content(stream, tag, [], [b . content], false, true, false)
94   - else if in_last_token then
95   - if b = '>' then //just found the end of bracket, so we return the token in LOWER case
96   - if to_lower(implode(reverse(so_far))) = tag then
97   - with content = implode(reverse(content)),
98   - println("Tag ["+tag+"] content found ["+content+"]");
99   - success(content)
100   - else
101   - failure
102   - else
103   - _xml_tag_content(stream, tag, [b . so_far], content, false, false, true)
104   -
105   - else
106   - if b = '<' then //just found the begin of token
107   - _xml_tag_content(stream, tag, [], [], true, false, false)
108   - else
109   - _xml_tag_content(stream, tag, [], [], false, false, false)
110   - }
111   - .
112   -define Maybe(String)
113   - xml_pair_tag_content
114   - (
115   - Stream stream,
116   - String tag
117   - )= _xml_tag_content( stream, tag, [], [], false, false, false).
118   -
119   -define Maybe(String)
120   - xml_tag_content
121   - (
122   - Stream stream,
123   - String tag
124   - )= _xml_tag_content( stream, tag, [], [], false, true, false).
125   -
126   - /***** ARRAY functions ******/
127   -
128   -define Maybe(List(XML_RPC_value))
129   - read_values
130   - (
131   - Stream stream,
132   - List(XML_RPC_value) so_far
133   - )=
134   - if read_value(stream) is
135   - {
136   - failure then failure,
137   - success(value) then
138   - if next_xml_token(stream) is
139   - {
140   - none then failure,
141   - token(token) then
142   -
143   - if token = "value" then //there is another value we read it
144   - read_values(stream, [value . so_far])
145   - else
146   - unput_string("<"+token+">", stream);
147   - success(reverse([value . so_far]))
148   - }
149   - }.
150   -
151   -define Maybe(List(XML_RPC_value))
152   - read_data
153   - (
154   - Stream stream
155   - )=
156   - if next_xml_token(stream) is
157   - {
158   - none then failure,
159   - token(token) then
160   - if token = "data" then
161   - if next_xml_token(stream) is
162   - {
163   - none then failure,
164   - token(token) then
165   - if token = "value" then
166   - if read_values(stream, []) is
167   - {
168   - failure then failure
169   - success(values) then
170   - if next_xml_token(stream) is
171   - {
172   - none then failure,
173   - token(token) then
174   - if token = "/data" then
175   - success(values)
176   - else
177   - failure
178   - }
179   - }
180   - else
181   - failure
182   - }
183   - else
184   - failure
185   - }.
186   -
187   -define Maybe(XML_RPC_value)
188   - read_array
189   - (
190   - Stream stream
191   - )=
192   - if read_data(stream) is
193   - {
194   - failure then failure
195   - success(values) then
196   - if next_xml_token(stream) is
197   - {
198   - none then failure,
199   - token(token) then
200   - if token = "/array" then
201   - success(array(array(values)))
202   - else
203   - failure
204   - }
205   - }.
206   -
207   - /***** STRUCT functions ******/
208   -
209   -define Maybe(List(XML_RPC_struct_member))
210   - read_members
211   - (
212   - Stream stream,
213   - List(XML_RPC_struct_member) so_far
214   - )=
215   - if xml_pair_tag_content(stream, "name") is
216   - {
217   - failure then failure,
218   - success(member_name) then
219   - if next_xml_token(stream) is
220   - {
221   - none then failure,
222   - token(tok) then
223   - if tok = "value" then
224   - if read_value(stream) is
225   - {
226   - failure then failure,
227   - success(value) then
228   - if next_xml_token(stream) is
229   - {
230   - none then failure,
231   - token(tok) then
232   - if tok = "/member" then
233   - if next_xml_token(stream) is
234   - {
235   - none then failure,
236   - token(tok) then
237   - if tok = "member" then //there is another member in structure, we read it
238   - read_members(stream, [member(member_name, value) . so_far])
239   - else if tok = "/struct" then //End of structrue found
240   - println("End struct");
241   - success(reverse([member(member_name, value) . so_far])) //return all members in right order
242   - else
243   - failure //unexpected token
244   - }
245   - else
246   - failure
247   - }
248   - }
249   - else
250   - failure
251   - }
252   - } .
253   -
254   -define Maybe(XML_RPC_value)
255   - read_struct
256   - (
257   - Stream stream
258   - )=
259   - if next_xml_token(stream) is
260   - {
261   - none then failure,
262   - token(token) then
263   - if token = "member" then
264   - if read_members(stream, []) is
265   - {
266   - failure then failure
267   - success(members_list) then success(struct(members(members_list)))
268   - }
269   - else
270   - failure
271   - }.
272   -
273   -define Maybe(XML_RPC_value)
274   - read_value
275   - (
276   - Stream stream
277   - )=
278   - if next_xml_token(stream) is
279   - {
280   - none then failure,
281   - token(token) then
282   - with value = if token = "string" then
283   - if xml_tag_content(stream, "string") is
284   - {
285   - failure then failure,
286   - success(v) then success(string(v))
287   - }
288   - else if token = "int" then
289   - if xml_tag_content(stream, "int") is
290   - {
291   - failure then failure,
292   - success(v) then
293   - if decimal_scan(v) is
294   - {
295   - failure then failure,
296   - success(int_v) then success(int(truncate_to_Word32(int_v)))
297   - }
298   - }
299   - else if token = "i4" then
300   - if xml_tag_content(stream, "i4") is
301   - {
302   - failure then failure,
303   - success(v) then
304   - if decimal_scan(v) is
305   - {
306   - failure then failure,
307   - success(int_v) then success(int(truncate_to_Word32(int_v)))
308   - }
309   - }
310   - else if token = "boolean" then
311   - if xml_tag_content(stream, "boolean") is
312   - {
313   - failure then failure,
314   - success(v) then success(bool(to_Bool(v)))
315   - }
316   - else if token = "double" then
317   - if xml_tag_content(stream, "string") is
318   - {
319   - failure then failure,
320   - success(v) then success(double(0.0))
321   - }
322   - else if token = "datetime" then
323   - if xml_tag_content(stream, "string") is
324   - {
325   - failure then failure,
326   - success(v) then success(datetime(v))
327   - }
328   - else if token = "base64" then
329   - if xml_tag_content(stream, "base64") is
330   - {
331   - failure then failure,
332   - success(b64) then success(base64(b64))
333   - }
334   - else if token = "struct" then read_struct(stream)
335   - else if token = "array" then read_array(stream)
336   - else
337   - failure,
338   - if next_xml_token(stream) is
339   - {
340   - none then failure
341   - token(token) then
342   - if token = "/value" then
343   - value
344   - else
345   - failure
346   - }
347   - }.
348   -
349   -define Maybe(XML_RPC_parameter)
350   - in_value
351   - (
352   - Stream stream,
353   - List(XML_RPC_value) so_far
354   - )=
355   - if next_xml_token(stream) is
356   - {
357   - none then failure,
358   - token(tok) then
359   - if tok = "value" then
360   - if read_value(stream) is
361   - {
362   - failure then failure,
363   - success(value) then in_value(stream, [ value. so_far])
364   - }
365   - else if tok = "/param" then
366   - success(parameter(reverse(so_far)))
367   - else
368   - failure
369   - }.
370   -
371   -define Maybe(XML_RPC_value)
372   - in_fault
373   - (
374   - Stream stream,
375   - )=
376   - if next_xml_token(stream) is
377   - {
378   - none then failure,
379   - token(tok) then
380   - if tok = "value" then
381   - if read_value(stream) is
382   - {
383   - failure then failure,
384   - success(value) then
385   - if next_xml_token(stream) is
386   - {
387   - none then failure,
388   - token(tok) then
389   - if tok = "/fault" then
390   - success(value)
391   - else
392   - failure
393   - }
394   - }
395   - else
396   - failure
397   - }.
398   -
399   -define Maybe(XML_RPC_parameters)
400   - in_param
401   - (
402   - Stream stream,
403   - List(XML_RPC_parameter) so_far
404   - )=
405   - if next_xml_token(stream) is
406   - {
407   - none then failure,
408   - token(tok) then
409   - if tok = "param" then
410   - if in_value(stream, []) is
411   - {
412   - failure then failure,
413   - success(param) then in_param(stream, [ param . so_far])
414   - }
415   -
416   - else if tok = "/params" then
417   - success(parameters(reverse(so_far)))
418   - else
419   - failure
420   - }
421   - .
422   -
423   -define Maybe(XML_RPC_response)
424   - in_params
425   - (
426   - Stream stream
427   - )=
428   - if next_xml_token(stream) is
429   - {
430   - none then failure,
431   - token(tok) then
432   - if tok = "params" then
433   - if in_param(stream, []) is
434   - {
435   - failure then failure,
436   - success(resp) then success(ok(resp))
437   - }
438   - else if tok = "fault" then
439   - if in_fault(stream) is
440   - {
441   - failure then failure,
442   - success(resp) then success(fault(resp))
443   - }
444   - else
445   - failure
446   - }
447   -
448   - .
449   -
450   -public define Maybe(XML_RPC_response)
451   - xml_rpc_get_response
452   - (
453   - String response
454   - )=
455   - with stream = make_stream(response),
456   - if next_xml_token(stream) is
457   - {
458   - none then failure
459   - token(tok) then
460   - if tok = "?xml version='1.0'?" then
461   - if next_xml_token(stream) is
462   - {
463   - none then failure
464   - token(tok) then
465   - if tok = "methodresponse" then
466   - in_params(stream)
467   - else
468   - failure
469   - }
470   - else
471   - failure
472   - }.
  1 +๏ปฟ/*
  2 + * Created by PyramIDE.
  3 + * User: Totoro
  4 + * Date: 06/07/2013
  5 + * Time: 01:13
  6 + *
  7 + */
  8 +
  9 +read calexium_lib/web/CXM_xml_rpc_types.anubis
  10 +read tools/streams.anubis
  11 +read tools/basis.anubis
  12 +read system/string.anubis
  13 +read system/convert.anubis
  14 +
  15 +type XML_RPC_Token:
  16 + none,
  17 + token(String token).
  18 +
  19 +define Maybe(XML_RPC_value) read_value(Stream stream).
  20 +
  21 +define XML_RPC_Token
  22 + _next_xml_token
  23 + (
  24 + Stream stream,
  25 + List(Word8) so_far,
  26 + Bool in_token
  27 + )=
  28 + if read_byte(stream) is
  29 + {
  30 + failure then none, //can't read on stream !!
  31 + success(b) then
  32 + //println("["+implode([b])+"]");
  33 + if in_token then
  34 + if b = '>' then //just found the end of bracket, so we return the token in LOWER case
  35 + with tok = to_lower(implode(reverse(so_far))),
  36 + //println("found tag "+tok);
  37 + token(tok)
  38 + else
  39 + _next_xml_token(stream, [b . so_far], in_token)
  40 + else
  41 + if b = '<' then //just found the begin of token
  42 + _next_xml_token(stream, [], true)
  43 + else
  44 + _next_xml_token(stream, so_far, in_token)
  45 + }
  46 + .
  47 +
  48 +
  49 +
  50 +define XML_RPC_Token
  51 + next_xml_token
  52 + (
  53 + Stream stream
  54 + )= _next_xml_token(stream, [], false).
  55 +
  56 +define Maybe(String)
  57 + _xml_tag_content
  58 + (
  59 + Stream stream,
  60 + String tag, //tag to match
  61 + List(Word8) so_far,
  62 + List(Word8) content,
  63 + Bool in_first_token,
  64 + Bool in_content,
  65 + Bool in_last_token
  66 +
  67 + )=
  68 + if read_byte(stream) is
  69 + {
  70 + failure then failure, //can't read on stream !!
  71 + success(b) then
  72 + if in_first_token then
  73 + if b = '>' then //just found the end of bracket, so we return the token in LOWER case
  74 + if to_lower(implode(reverse(so_far))) = tag then
  75 + _xml_tag_content(stream, tag, [], [], false, true, false)
  76 + else
  77 + failure
  78 + else
  79 + _xml_tag_content(stream, tag, [b . so_far], content, in_first_token, in_content, in_last_token)
  80 + else if in_content then
  81 + if b = '<' then //just found the begin bracket,
  82 + if read_byte(stream) is
  83 + {
  84 + failure then failure, //can't read on stream !!
  85 + success(b) then
  86 + if b = '/' then //can't find / => syntax error
  87 + _xml_tag_content(stream, tag, [], content, false, false, true)
  88 + else
  89 + failure
  90 + }
  91 + else
  92 + _xml_tag_content(stream, tag, [], [b . content], false, true, false)
  93 + else if in_last_token then
  94 + if b = '>' then //just found the end of bracket, so we return the token in LOWER case
  95 + if to_lower(implode(reverse(so_far))) = tag then
  96 + with content = implode(reverse(content)),
  97 + println("Tag ["+tag+"] content found ["+content+"]");
  98 + success(content)
  99 + else
  100 + failure
  101 + else
  102 + _xml_tag_content(stream, tag, [b . so_far], content, false, false, true)
  103 +
  104 + else
  105 + if b = '<' then //just found the begin of token
  106 + _xml_tag_content(stream, tag, [], [], true, false, false)
  107 + else
  108 + _xml_tag_content(stream, tag, [], [], false, false, false)
  109 + }
  110 + .
  111 +define Maybe(String)
  112 + xml_pair_tag_content
  113 + (
  114 + Stream stream,
  115 + String tag
  116 + )= _xml_tag_content( stream, tag, [], [], false, false, false).
  117 +
  118 +define Maybe(String)
  119 + xml_tag_content
  120 + (
  121 + Stream stream,
  122 + String tag
  123 + )= _xml_tag_content( stream, tag, [], [], false, true, false).
  124 +
  125 + /***** ARRAY functions ******/
  126 +
  127 +define Maybe(List(XML_RPC_value))
  128 + read_values
  129 + (
  130 + Stream stream,
  131 + List(XML_RPC_value) so_far
  132 + )=
  133 + if read_value(stream) is
  134 + {
  135 + failure then failure,
  136 + success(value) then
  137 + if next_xml_token(stream) is
  138 + {
  139 + none then failure,
  140 + token(token) then
  141 +
  142 + if token = "value" then //there is another value we read it
  143 + read_values(stream, [value . so_far])
  144 + else
  145 + unput_string("<"+token+">", stream);
  146 + success(reverse([value . so_far]))
  147 + }
  148 + }.
  149 +
  150 +define Maybe(List(XML_RPC_value))
  151 + read_data
  152 + (
  153 + Stream stream
  154 + )=
  155 + if next_xml_token(stream) is
  156 + {
  157 + none then failure,
  158 + token(token) then
  159 + if token = "data" then
  160 + if next_xml_token(stream) is
  161 + {
  162 + none then failure,
  163 + token(token) then
  164 + if token = "value" then
  165 + if read_values(stream, []) is
  166 + {
  167 + failure then failure
  168 + success(values) then
  169 + if next_xml_token(stream) is
  170 + {
  171 + none then failure,
  172 + token(token) then
  173 + if token = "/data" then
  174 + success(values)
  175 + else
  176 + failure
  177 + }
  178 + }
  179 + else
  180 + failure
  181 + }
  182 + else
  183 + failure
  184 + }.
  185 +
  186 +define Maybe(XML_RPC_value)
  187 + read_array
  188 + (
  189 + Stream stream
  190 + )=
  191 + if read_data(stream) is
  192 + {
  193 + failure then failure
  194 + success(values) then
  195 + if next_xml_token(stream) is
  196 + {
  197 + none then failure,
  198 + token(token) then
  199 + if token = "/array" then
  200 + success(array(array(values)))
  201 + else
  202 + failure
  203 + }
  204 + }.
  205 +
  206 + /***** STRUCT functions ******/
  207 +
  208 +define Maybe(List(XML_RPC_struct_member))
  209 + read_members
  210 + (
  211 + Stream stream,
  212 + List(XML_RPC_struct_member) so_far
  213 + )=
  214 + if xml_pair_tag_content(stream, "name") is
  215 + {
  216 + failure then failure,
  217 + success(member_name) then
  218 + if next_xml_token(stream) is
  219 + {
  220 + none then failure,
  221 + token(tok) then
  222 + if tok = "value" then
  223 + if read_value(stream) is
  224 + {
  225 + failure then failure,
  226 + success(value) then
  227 + if next_xml_token(stream) is
  228 + {
  229 + none then failure,
  230 + token(tok) then
  231 + if tok = "/member" then
  232 + if next_xml_token(stream) is
  233 + {
  234 + none then failure,
  235 + token(tok) then
  236 + if tok = "member" then //there is another member in structure, we read it
  237 + read_members(stream, [member(member_name, value) . so_far])
  238 + else if tok = "/struct" then //End of structrue found
  239 + println("End struct");
  240 + success(reverse([member(member_name, value) . so_far])) //return all members in right order
  241 + else
  242 + failure //unexpected token
  243 + }
  244 + else
  245 + failure
  246 + }
  247 + }
  248 + else
  249 + failure
  250 + }
  251 + } .
  252 +
  253 +define Maybe(XML_RPC_value)
  254 + read_struct
  255 + (
  256 + Stream stream
  257 + )=
  258 + if next_xml_token(stream) is
  259 + {
  260 + none then failure,
  261 + token(token) then
  262 + if token = "member" then
  263 + if read_members(stream, []) is
  264 + {
  265 + failure then failure
  266 + success(members_list) then success(struct(members(members_list)))
  267 + }
  268 + else
  269 + failure
  270 + }.
  271 +
  272 +define Maybe(XML_RPC_value)
  273 + read_value
  274 + (
  275 + Stream stream
  276 + )=
  277 + if next_xml_token(stream) is
  278 + {
  279 + none then failure,
  280 + token(token) then
  281 + with value = if token = "string" then
  282 + if xml_tag_content(stream, "string") is
  283 + {
  284 + failure then failure,
  285 + success(v) then success(string(v))
  286 + }
  287 + else if token = "int" then
  288 + if xml_tag_content(stream, "int") is
  289 + {
  290 + failure then failure,
  291 + success(v) then
  292 + if decimal_scan(v) is
  293 + {
  294 + failure then failure,
  295 + success(int_v) then success(int(truncate_to_Word32(int_v)))
  296 + }
  297 + }
  298 + else if token = "i4" then
  299 + if xml_tag_content(stream, "i4") is
  300 + {
  301 + failure then failure,
  302 + success(v) then
  303 + if decimal_scan(v) is
  304 + {
  305 + failure then failure,
  306 + success(int_v) then success(int(truncate_to_Word32(int_v)))
  307 + }
  308 + }
  309 + else if token = "boolean" then
  310 + if xml_tag_content(stream, "boolean") is
  311 + {
  312 + failure then failure,
  313 + success(v) then success(bool(to_Bool(v)))
  314 + }
  315 + else if token = "double" then
  316 + if xml_tag_content(stream, "string") is
  317 + {
  318 + failure then failure,
  319 + success(v) then success(double(0.0))
  320 + }
  321 + else if token = "datetime" then
  322 + if xml_tag_content(stream, "string") is
  323 + {
  324 + failure then failure,
  325 + success(v) then success(datetime(v))
  326 + }
  327 + else if token = "base64" then
  328 + if xml_tag_content(stream, "base64") is
  329 + {
  330 + failure then failure,
  331 + success(b64) then success(base64(b64))
  332 + }
  333 + else if token = "struct" then read_struct(stream)
  334 + else if token = "array" then read_array(stream)
  335 + else
  336 + failure,
  337 + if next_xml_token(stream) is
  338 + {
  339 + none then failure
  340 + token(token) then
  341 + if token = "/value" then
  342 + value
  343 + else
  344 + failure
  345 + }
  346 + }.
  347 +
  348 +define Maybe(XML_RPC_parameter)
  349 + in_value
  350 + (
  351 + Stream stream,
  352 + List(XML_RPC_value) so_far
  353 + )=
  354 + if next_xml_token(stream) is
  355 + {
  356 + none then failure,
  357 + token(tok) then
  358 + if tok = "value" then
  359 + if read_value(stream) is
  360 + {
  361 + failure then failure,
  362 + success(value) then in_value(stream, [ value. so_far])
  363 + }
  364 + else if tok = "/param" then
  365 + success(parameter(reverse(so_far)))
  366 + else
  367 + failure
  368 + }.
  369 +
  370 +define Maybe(XML_RPC_value)
  371 + in_fault
  372 + (
  373 + Stream stream,
  374 + )=
  375 + if next_xml_token(stream) is
  376 + {
  377 + none then failure,
  378 + token(tok) then
  379 + if tok = "value" then
  380 + if read_value(stream) is
  381 + {
  382 + failure then failure,
  383 + success(value) then
  384 + if next_xml_token(stream) is
  385 + {
  386 + none then failure,
  387 + token(tok) then
  388 + if tok = "/fault" then
  389 + success(value)
  390 + else
  391 + failure
  392 + }
  393 + }
  394 + else
  395 + failure
  396 + }.
  397 +
  398 +define Maybe(XML_RPC_parameters)
  399 + in_param
  400 + (
  401 + Stream stream,
  402 + List(XML_RPC_parameter) so_far
  403 + )=
  404 + if next_xml_token(stream) is
  405 + {
  406 + none then failure,
  407 + token(tok) then
  408 + if tok = "param" then
  409 + if in_value(stream, []) is
  410 + {
  411 + failure then failure,
  412 + success(param) then in_param(stream, [ param . so_far])
  413 + }
  414 +
  415 + else if tok = "/params" then
  416 + success(parameters(reverse(so_far)))
  417 + else
  418 + failure
  419 + }
  420 + .
  421 +
  422 +define Maybe(XML_RPC_response)
  423 + in_params
  424 + (
  425 + Stream stream
  426 + )=
  427 + if next_xml_token(stream) is
  428 + {
  429 + none then failure,
  430 + token(tok) then
  431 + if tok = "params" then
  432 + if in_param(stream, []) is
  433 + {
  434 + failure then failure,
  435 + success(resp) then success(ok(resp))
  436 + }
  437 + else if tok = "fault" then
  438 + if in_fault(stream) is
  439 + {
  440 + failure then failure,
  441 + success(resp) then success(fault(resp))
  442 + }
  443 + else
  444 + failure
  445 + }
  446 +
  447 + .
  448 +
  449 +public define Maybe(XML_RPC_response)
  450 + xml_rpc_get_response
  451 + (
  452 + String response
  453 + )=
  454 + with stream = make_stream(response),
  455 + if next_xml_token(stream) is
  456 + {
  457 + none then failure
  458 + token(tok) then
  459 + if tok = "?xml version='1.0'?" then
  460 + if next_xml_token(stream) is
  461 + {
  462 + none then failure
  463 + token(tok) then
  464 + if tok = "methodresponse" then
  465 + in_params(stream)
  466 + else
  467 + failure
  468 + }
  469 + else
  470 + failure
  471 + }.
... ...