vs2003->vs2005时就注意的事项(转)

ASP.NET 1.1至2.0迁移心得
本文分享了将CommunityServer从ASP.NET 1.1迁移到ASP.NET 2.0的过程及经验教训,包括解决语法错误、去除冗余声明以及更新Membership配置等方面的内容。

费了好一袋烟工夫把CommunityServer升级到了Asp.Net2.0平台,一点心得:

vs2005可以很方便的帮我们把vs2003开发的asp.net1.1版本项目升级到vs2005开发的asp.net2.0版本,从vs2005里面打开vs2003的解决方案或者项目文件,会有向导帮我们自己完成升级工作。一部分asp.net1.1的项目做完这个工作就足够了。

不过更多的时候不会这么顺利,还要注意一些问题:

  • vs2003开发的asp.net1.1程序,不会检查aspx、aspcx等文件中的语法错误,而vs2005会检查项目中所有的aspx、aspcx等文件中的语法,所以如果有语法错误,会导致编译无法通过。
  • vs2003中,如果用的是默认的代码绑定方式,那么在aspx文件(以aspx文件为例,ascx文件也有这个问题)中申明的服务器端控件,会在aspx文件对应的aspx.cs文件中,生成一个对应的申明,例如aspx中有一个TextBox,ID是MyTextBox,那么在aspx.cs中,会申明一个"protected TextBox MyTextBox;",而在vs2005中,这个申明是多余的,所以升级后要去除这些多余的申明。
  • 如果有程序采用了asp.net1.1下的Membership——使用MemberRole.dll,要升级到asp.net2.0下的Membership,需要做如下工作:
    • 删除所有项目中对"MemberRole.dll"的引用,添加"System.Configration"的引用
    • 改变命名空间ScalableHosting.Profile -> System.Web.Profile;ScalableHosting.Security -> System.Web.Security; 同时添加using System.Configuration;
    • 移除所有MemberRole.dll相关的Membership配置,参照以前的Membership配置,增加asp.net2.0支持的Membership配置,更新Membership的存储过程。
  • CCS1.1 for asp.net2.0的下载:http://www.communityserver.cn/builds 
static void oplus_vooc_switch_check_work(struct work_struct *work) 1719 { 1720 struct delayed_work *dwork = to_delayed_work(work); 1721 struct oplus_chg_vooc *chip = container_of(dwork, struct oplus_chg_vooc, 1722 vooc_switch_check_work); 1723 int chg_type; 1724 bool present = false; 1725 bool retry_flag = false; 1726 static unsigned long fastchg_check_timeout; 1727 unsigned long schedule_delay = 0; 1728 int rc; 1729 union mms_msg_data data = { 0 }; 1730 struct timespec64 uptime; 1731 1732 chg_info("vooc switch check\n"); 1733 1734 rc = oplus_vooc_cpa_switch_start(chip); 1735 if (rc < 0) { 1736 chg_info("cpa protocol not vooc, return\n"); 1737 return; 1738 } 1739 if (!chip->config.svooc_support) { 1740 chg_info("The SVOOC project does not allow fast charge" 1741 "again after the VOOC adapter is recognized\n"); 1742 oplus_vooc_cpa_switch_end(chip); 1743 return; 1744 } 1745 1746 present = oplus_wired_is_present(); 1747 if (!present) { 1748 if (!chip->vooc_online) { 1749 chip->switch_retry_count = 0; 1750 oplus_vooc_cpa_switch_end(chip); 1751 } 1752 chg_info("vooc_online = %d, present is false, return\n", chip->vooc_online); 1753 return; 1754 } 1755 1756 if (chip->abnormal_adapter_dis_cnt > 0 && 1757 chip->support_abnormal_over_80w_adapter && 1758 (chip->pre_is_abnormal_adapter & ABNOMAL_ADAPTER_IS_OVER_80W_ADAPTER)) { 1759 if (chip->abnormal_adapter_dis_cnt >= chip->abnormal_over_80w_adapter_cur_arraycnt) { 1760 chg_info("abnormal over_80w adapter dis cnt is %d >= vooc_max, switch to noraml and clear the count \n", 1761 chip->abnormal_adapter_dis_cnt); 1762 chip->abnormal_adapter_dis_cnt = 0; 1763 oplus_chg_clear_abnormal_adapter_var(chip); 1764 if (oplus_chg_vooc_get_switch_mode(chip->vooc_ic) != 1765 VOOC_SWITCH_MODE_NORMAL) { 1766 switch_normal_chg(chip->vooc_ic); 1767 oplus_vooc_set_reset_sleep(chip->vooc_ic); 1768 } 1769 oplus_vooc_cpa_switch_end(chip); 1770 return; 1771 } 1772 } else if (chip->abnormal_adapter_dis_cnt > 0 && 1773 chip->support_abnormal_adapter && 1774 (chip->pre_is_abnormal_adapter & ABNOMAL_ADAPTER_IS_65W_ABNOMAL_ADAPTER) && 1775 (chip->abnormal_adapter_dis_cnt >= chip->abnormal_adapter_cur_arraycnt)) { 1776 chg_info("abnormal adapter dis cnt is %d >= vooc_max, switch to noraml and clear the count\n", 1777 chip->abnormal_adapter_dis_cnt); 1778 chip->abnormal_adapter_dis_cnt = 0; 1779 oplus_chg_clear_abnormal_adapter_var(chip); 1780 if (oplus_chg_vooc_get_switch_mode(chip->vooc_ic) != 1781 VOOC_SWITCH_MODE_NORMAL) { 1782 switch_normal_chg(chip->vooc_ic); 1783 oplus_vooc_set_reset_sleep(chip->vooc_ic); 1784 } 1785 oplus_vooc_cpa_switch_end(chip); 1786 return; 1787 } 1788 1789 if (chip->fastchg_disable) { 1790 chip->switch_retry_count = 0; 1791 chg_info("fastchg disable, return\n"); 1792 oplus_vooc_cpa_switch_end(chip); 1793 return; 1794 } 1795 if (chip->fastchg_started) { 1796 chip->switch_retry_count = 0; 1797 chg_err("fastchg_started=%d\n", chip->fastchg_started); 1798 return; 1799 } 1800 1801 if (chip->cpa_support) 1802 chg_type = oplus_vooc_get_real_wired_type(chip); 1803 else 1804 chg_type = oplus_wired_get_chg_type(); 1805 if ((chip->ufcs_vid == OPLUS_SVID) && 1806 (chg_type == OPLUS_CHG_USB_TYPE_PD_PPS || chg_type == OPLUS_CHG_USB_TYPE_PD)) { 1807 chg_err("chg type is pd/pps and get ufcs vid is 0x22d9, enable pd svooc\n"); 1808 vote(chip->pd_svooc_votable, SVID_VOTER, true, 1, false); 1809 } 1810 /* The cpa module will ensure the correctness of the type*/ 1811 if (!chip->cpa_support) { 1812 switch (chg_type) { 1813 case OPLUS_CHG_USB_TYPE_DCP: 1814 case OPLUS_CHG_USB_TYPE_ACA: 1815 case OPLUS_CHG_USB_TYPE_APPLE_BRICK_ID: 1816 case OPLUS_CHG_USB_TYPE_SVOOC: 1817 case OPLUS_CHG_USB_TYPE_VOOC: 1818 break; 1819 case OPLUS_CHG_USB_TYPE_PD: 1820 case OPLUS_CHG_USB_TYPE_PD_PPS: 1821 if (!chip->pd_svooc) { 1822 chip->switch_retry_count = 0; 1823 chg_info("pd_svooc=false\n"); 1824 return; 1825 } 1826 break; 1827 default: 1828 chip->switch_retry_count = 0; 1829 chg_info("chg_type=%s, not support fastchg\n", 1830 oplus_wired_get_chg_type_str(chg_type)); 1831 return; 1832 } 1833 } else { 1834 /* The cpa module not ensure pd_svooc when pd_pps*/ 1835 if ((chg_type == OPLUS_CHG_USB_TYPE_PD_PPS || 1836 chg_type == OPLUS_CHG_USB_TYPE_PD) && 1837 !chip->pd_svooc) { 1838 reinit_completion(&chip->pdsvooc_check_ack); 1839 rc = wait_for_completion_timeout(&chip->pdsvooc_check_ack, 1840 msecs_to_jiffies(PDSVOOC_CHECK_WAIT_TIME_MS)); 1841 chg_info("pdsvooc check ack rc: %d, pd_svooc: %d\n", rc, chip->pd_svooc); 1842 if (!rc || !chip->pd_svooc) { 1843 chip->switch_retry_count = 0; 1844 oplus_cpa_switch_end(chip->cpa_topic, CHG_PROTOCOL_VOOC); 1845 return; 1846 } 1847 } 1848 } 1849 1850 reinit_completion(&chip->vooc_wait_bc12); 1851 chg_info("chg_type=%d\n", chg_type); 1852 if (chg_type == OPLUS_CHG_USB_TYPE_UNKNOWN) { 1853 wait_for_completion_timeout( 1854 &chip->vooc_wait_bc12, 1855 msecs_to_jiffies(VOOC_WAIT_BC1P2_GET_TYPE)); 1856 chg_type = oplus_wired_get_chg_type(); 1857 if (chg_type == OPLUS_CHG_USB_TYPE_UNKNOWN || chip->fastchg_started) { 1858 if (!chip->vooc_online) { 1859 chip->switch_retry_count = 0; 1860 oplus_cpa_switch_end(chip->cpa_topic, CHG_PROTOCOL_VOOC); 1861 } 1862 return; 1863 } 1864 } 1865 1866 if (chip->switch_retry_count == 0 && oplus_wired_get_ibus() < BEFORE_VOOC_CURR_CHECK) { 1867 rc = oplus_mms_get_item_data(chip->wired_topic, WIRED_ITEM_ICL_DONE_STATUS, &data, true); 1868 if (rc == 0 && data.intval == 0) { 1869 reinit_completion(&chip->icl_done_ack); 1870 rc = wait_for_completion_timeout(&chip->icl_done_ack, 1871 msecs_to_jiffies(WAIT_CURR_STARUP)); 1872 chg_info("wait wired icl done over\n"); 1873 } 1874 } 1875 1876 chg_info("switch_retry_count=%d, fast_chg_status=%d fastchg_check_timeout=%lu\n", 1877 chip->switch_retry_count, chip->fast_chg_status, fastchg_check_timeout); 1878 if (chip->switch_retry_count == 0) { 1879 if (oplus_chg_get_boot_reset_adapter_support_flags() && !chip->check_boot_reset_adapter) { 1880 ktime_get_boottime_ts64(&uptime); 1881 if ((unsigned long)uptime.tv_sec < BOOT_RESETADAPTER_20S) { 1882 chip->check_boot_reset_adapter = true; 1883 chip->reset_adapter = true; 1884 } 1885 } 1886 if ((chip->fast_chg_status == 1887 CHARGER_STATUS_SWITCH_TEMP_RANGE || 1888 chip->fast_chg_status == CHARGER_STATUS_FAST_TO_WARM || 1889 chip->fast_chg_status == CHARGER_STATUS_FAST_DUMMY || 1890 chip->fast_chg_status == CHARGER_STATUS_TIMEOUT_RETRY || 1891 chip->fast_chg_status == CHARGER_STATUS_CURR_LIMIT || 1892 chip->reset_adapter) && 1893 oplus_vooc_is_allow_fast_chg(chip) && 1894 is_wired_charge_suspend_votable_available(chip)) { 1895 chg_info("fast_chg_status=%d reset adapter\n", 1896 chip->fast_chg_status); 1897 chip->reset_adapter = false; 1898 /* Reset adapter */ 1899 oplus_reset_adapter(chip); 1900 } 1901 1902 fastchg_check_timeout = jiffies; 1903 chg_err("switch to fastchg, jiffies=%lu\n", fastchg_check_timeout); 1904 1905 chip->switch_retry_count++; 1906 oplus_vooc_switch_fast_chg(chip); 1907 schedule_delayed_work(&chip->vooc_switch_check_work, msecs_to_jiffies(5000)); 1908 return; 1909 1910 } else if (chip->switch_retry_count <= RETRY_15S_COUNT) { 1911 if ((chip->switch_retry_count == 1) && 1912 time_is_after_jiffies(fastchg_check_timeout + (unsigned long)(5 * HZ))) { 1913 schedule_delay = fastchg_check_timeout + (unsigned long)(5 * HZ) - jiffies; 1914 schedule_delayed_work(&chip->vooc_switch_check_work, schedule_delay); 1915 chg_err("Concurrent invalid calls lead to early triggering." 1916 "The 5s interval has not expired, so continue to wait %lu jiffies\n", 1917 schedule_delay); 1918 return; 1919 } else if ((chip->switch_retry_count == RETRY_15S_COUNT) && 1920 time_is_after_jiffies(fastchg_check_timeout + (unsigned long)(15 * HZ))) { 1921 schedule_delay = fastchg_check_timeout + (unsigned long)(15 * HZ) - jiffies; 1922 schedule_delayed_work(&chip->vooc_switch_check_work, schedule_delay); 1923 chg_err("Concurrent invalid calls lead to early triggering." 1924 "The 15s interval has not expired, so continue to wait %lu jiffies\n", 1925 schedule_delay); 1926 return; 1927 } 1928 1929 oplus_vooc_get_retry_flag(chip->vooc_ic, &retry_flag); 1930 if (chip->switch_retry_count == 1 && !retry_flag) { 1931 chip->switch_retry_count++; 1932 schedule_delayed_work(&chip->vooc_switch_check_work, msecs_to_jiffies(10000)); 1933 return; 1934 } 1935 if (is_wired_charge_suspend_votable_available(chip)) { 1936 if (chip->vooc_ic->type == OPLUS_CHG_IC_VIRTUAL_VPHY) 1937 switch_normal_chg(chip->vooc_ic); 1938 /* Reset adapter */ 1939 oplus_reset_adapter(chip); 1940 } 1941 if (chip->wired_online && 1942 (oplus_chg_vooc_get_switch_mode(chip->vooc_ic) != 1943 VOOC_SWITCH_MODE_VOOC)) { 1944 switch_fast_chg(chip->vooc_ic); 1945 chg_err("D+D- did not switch to VOOC mode, try switching\n"); 1946 } 1947 oplus_vooc_set_reset_active(chip->vooc_ic); 1948 if (chip->switch_retry_count == RETRY_15S_COUNT) 1949 schedule_delayed_work(&chip->vooc_switch_check_work, msecs_to_jiffies(15000)); 1950 else 1951 schedule_delayed_work(&chip->vooc_switch_check_work, msecs_to_jiffies(10000)); 1952 chip->switch_retry_count++; 1953 return; 1954 } else { 1955 if ((chip->switch_retry_count == 3) && 1956 time_is_after_jiffies(fastchg_check_timeout + (unsigned long)(30 * HZ))) { 1957 schedule_delay = fastchg_check_timeout + (unsigned long)(30 * HZ) - jiffies; 1958 schedule_delayed_work(&chip->vooc_switch_check_work, schedule_delay); 1959 chg_err("Concurrent invalid calls lead to early triggering." 1960 "The 30s interval has not expired, so continue to wait %lu jiffies\n", 1961 schedule_delay); 1962 return; 1963 } 1964 1965 chip->switch_retry_count = 0; 1966 switch_normal_chg(chip->vooc_ic); 1967 oplus_vooc_set_reset_sleep(chip->vooc_ic); 1968 1969 if (chg_type == OPLUS_CHG_USB_TYPE_QC2 || 1970 chg_type == OPLUS_CHG_USB_TYPE_QC3 || 1971 chg_type == OPLUS_CHG_USB_TYPE_DCP || 1972 chg_type == OPLUS_CHG_USB_TYPE_APPLE_BRICK_ID) { 1973 if (is_wired_charge_suspend_votable_available(chip)) { 1974 chg_err("reset adapter before detect qc\n"); 1975 vote(chip->wired_charge_suspend_votable, ADAPTER_RESET_VOTER, true, 1, false); 1976 if (chip->wired_online) 1977 msleep(MSLEEP_1000MS); 1978 vote(chip->wired_charge_suspend_votable, ADAPTER_RESET_VOTER, false, 0, false); 1979 if (chip->wired_online) 1980 msleep(MSLEEP_500MS); 1981 } 1982 if (!chip->cpa_support) { 1983 chg_err("detect qc\n"); 1984 oplus_qc_check_setup_timer(chip, QC_CHECK_TIMER); 1985 oplus_wired_qc_detect_enable(true); 1986 } else { 1987 oplus_cpa_request(chip->cpa_topic, CHG_PROTOCOL_QC); 1988 } 1989 } 1990 if (chip->cpa_support && chip->pd_svooc) { 1991 /* recheck pd */ 1992 oplus_cpa_request(chip->cpa_topic, CHG_PROTOCOL_PD); 1993 } 1994 1995 if (chip->wired_online) 1996 vote(chip->vooc_disable_votable, TIMEOUT_VOTER, true, 1, false); 1997 vote(chip->pd_svooc_votable, DEF_VOTER, false, 0, false); 1998 vote(chip->pd_svooc_votable, SVID_VOTER, false, 0, false); 1999 oplus_cpa_switch_end(chip->cpa_topic, CHG_PROTOCOL_VOOC); 2000 return; 2001 } 2002 } 2003 逐行注释
11-20
/****************************************************************************** Copyright © 2018-2018 TP-Link Systems Inc. Filename: soap.c Version: 1.0 Description: soap 处理函数 Author: liyijieliyijie@tp-link.com.cn Date: 2018-12-03 ******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <arpa/inet.h> #include “onvif_passthrough.h” #include “soap_global.h” #include “soap_parse.h” #include “soap_pack.h” #define SOAP_TAG_NUM 256 /定义最多可以注册256个标签处理函数/ typedef struct _SOAP_TAG_HANDLE { char tag[LEN_TAG]; S32 (*handle)(SOAP_CONTEXT *soap); }SOAP_TAG_HANDLE; /SOAP_TAG_HANDLE:结构体,包含一个标签字符串和一个处理函数指针/ LOCAL SOAP_TAG_HANDLE g_soap_tag_handle[SOAP_TAG_NUM]; /全局数组,用于存储注册的标签处理函数。/ /****************************************************************************** 函数名称: new_soap() 函数描述: 申请soap结构体 输 入: N/A 输 出: N/A 返 回 值: soap结构体地址 ******************************************************************************/ SOAP_CONTEXT *new_soap() { SOAP_CONTEXT *soap = NULL; soap = (SOAP_CONTEXT *)ONVIF_MALLOC(sizeof(SOAP_CONTEXT)); if (soap == NULL) { ONVIF_ERROR(“malloc g_soap_for_discv failed”); return NULL; } memset(soap, 0, sizeof(SOAP_CONTEXT)); if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN)) { ONVIF_FREE(soap); return NULL; } return soap; } /****************************************************************************** 函数名称: free_soap() 函数描述: 释放soap结构体 输 入: soap – soap结构体地址 输 出: N/A 返 回 值: N/A ******************************************************************************/ void free_soap(SOAP_CONTEXT *soap) { if (soap == NULL) { return; } if (soap->fault != NULL) { ONVIF_FREE(soap->fault->soap_env_value); ONVIF_FREE(soap->fault->soap_env_subcode_1); ONVIF_FREE(soap->fault->soap_env_subcode_2); ONVIF_FREE(soap->fault->soap_env_reason); ONVIF_FREE(soap->fault); } onvif_free_buf(&soap->xml_buf); ONVIF_FREE(soap); return; } /****************************************************************************** 函数名称: soap_init() 函数描述: 初始化soap结构体 输 入: soap – soap结构体地址 输 出: N/A 返 回 值: N/A ******************************************************************************/ void soap_init(SOAP_CONTEXT *soap) { if (soap == NULL) { ONVIF_WARN(“soap == NULL.); return; } soap->error = OK; soap->in_ip = 0; soap->ifindex = -1; soap->has_header = FALSE; memset(&soap->header, 0, sizeof(SOAP_ENV_HEADER)); if (soap->fault != NULL) { ONVIF_FREE(soap->fault->soap_env_value); ONVIF_FREE(soap->fault->soap_env_subcode_1); ONVIF_FREE(soap->fault->soap_env_subcode_2); ONVIF_FREE(soap->fault->soap_env_reason); ONVIF_FREE(soap->fault); soap->fault = NULL; } soap->tag[0] = ‘\0’; soap->request_begin = NULL; soap->request_end = NULL; soap->types[0] = ‘\0’; soap->scopes_item[0] = ‘\0’; soap->scopes_matchby[0] = ‘\0’; if (soap->xml_buf.start == NULL || (soap->xml_buf.end - soap->xml_buf.start) > ONVIF_DISCV_BUF_LEN) { if (OK != onvif_create_buf(&soap->xml_buf, ONVIF_DISCV_BUF_LEN)) { soap->xml_buf.start = NULL; soap->xml_buf.last = NULL; soap->xml_buf.end = NULL; } } soap->xml_buf.last = soap->xml_buf.start; return; } /****************************************************************************** 函数名称: soap_out_env_fault() 函数描述: 组装错误信息报文内容 输 入: xml_buf – 存放输出xml字串的内存地址 fault_data -- 错误信息 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ LOCAL S32 soap_out_env_fault(ONVIF_BUF *xml_buf, SOAP_ENV_FAULT *fault_data) { char attr[LEN_ANY] = {0}; if (xml_buf == NULL) { ONVIF_WARN(“xml_buf == NULL.); return ERROR; } /* SOAP-ENV:Fault begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, G_SOAP_ENV_FAULT_STR, NULL)); /* SOAP-ENV:Code begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, “SOAP-ENV:Code”, NULL)); /* SOAP-ENV:Value */ SOAP_IF_FAIL_RET(soap_element(xml_buf, “SOAP-ENV:Value”, fault_data->soap_env_value, NULL)); if (fault_data && fault_data->soap_env_subcode_1) { /* SOAP-ENV:Subcode begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, “SOAP-ENV:Subcode”, NULL)); /* SOAP-ENV:Value */ SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_subcode_1, NULL)); if (fault_data->soap_env_subcode_2) { /* SOAP-ENV:Subcode begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, "SOAP-ENV:Subcode", NULL)); /* SOAP-ENV:Value */ SOAP_IF_FAIL_RET(soap_element(xml_buf, "SOAP-ENV:Value", fault_data->soap_env_subcode_2, NULL)); /* SOAP-ENV:Subcode end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Subcode")); } /* SOAP-ENV:Subcode end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, "SOAP-ENV:Subcode")); } /* SOAP-ENV:Code end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, “SOAP-ENV:Code”)); /* SOAP-ENV:Reason begin */ SOAP_IF_FAIL_RET(soap_element_begin_out(xml_buf, “SOAP-ENV:Reason”, NULL)); /* SOAP-ENV:Text */ snprintf(attr, sizeof(attr), “xml:lang="en"”); SOAP_IF_FAIL_RET(soap_element(xml_buf, “SOAP-ENV:Text”, fault_data->soap_env_reason, attr)); /* SOAP-ENV:Reason end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, “SOAP-ENV:Reason”)); /* SOAP-ENV:Fault end */ SOAP_IF_FAIL_RET(soap_element_end_out(xml_buf, G_SOAP_ENV_FAULT_STR)); return OK; } /****************************************************************************** 函数名称: soap_fault() 函数描述: 填充错误信息结构体内容 输 入: soap – soap结构体地址 code -- 错误码 subcode1 -- 子错误码1 subcode2 -- 子错误码2 reason -- 错误原因 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_fault(SOAP_CONTEXT *soap, char *code, char *subcode1, char *subcode2, char *reason) { ONVIF_TRACE(“Onvif_fault\n”); if (soap == NULL || code == NULL || subcode1 == NULL) { ONVIF_TRACE(“soap == NULL || code == NULL || subcode1 == NULL.); return ERROR; } if (soap->fault) { ONVIF_FREE(soap->fault->soap_env_value); ONVIF_FREE(soap->fault->soap_env_subcode_1); ONVIF_FREE(soap->fault->soap_env_subcode_2); ONVIF_FREE(soap->fault->soap_env_reason); } else { soap->fault = ONVIF_MALLOC(sizeof(SOAP_ENV_FAULT)); } if (NULL == soap->fault) { ONVIF_WARN(“ONVIF_MALLOC fault failed.); return ERROR; } memset(soap->fault, 0, sizeof(SOAP_ENV_FAULT)); soap->fault->soap_env_value = ONVIF_STRDUP(code); if (NULL == soap->fault->soap_env_value) { ONVIF_WARN(“ONVIF_STRDUP soap_env_value failed.); return ERROR; } soap->fault->soap_env_subcode_1 = ONVIF_STRDUP(subcode1); if (NULL == soap->fault->soap_env_subcode_1) { ONVIF_WARN(“ONVIF_STRDUP soap_env_subcode_1 failed.); return ERROR; } if (subcode2) { soap->fault->soap_env_subcode_2 = ONVIF_STRDUP(subcode2); if (NULL == soap->fault->soap_env_subcode_2) { ONVIF_WARN(“ONVIF_STRDUP soap_env_subcode_2 failed.); return ERROR; } } if (reason) { soap->fault->soap_env_reason = ONVIF_STRDUP(reason); if (NULL == soap->fault->soap_env_reason) { ONVIF_WARN(“ONVIF_STRDUP soap_env_reason failed.); return ERROR; } } return OK; } /****************************************************************************** 函数名称: soap_generate_fault() 函数描述: 组装错误报文xml内容 输 入: soap – soap结构体地址 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ LOCAL S32 soap_generate_fault(SOAP_CONTEXT *soap) { if (soap == NULL) { ONVIF_WARN(“soap == NULL.); return ERROR; } //soap_set_fault(soap); if (soap->fault == NULL) { return ERROR; } if (soap->error < 200 && soap->error != SOAP_FAULT) { soap->has_header = FALSE; } return soap_generate_xml((p_out_fun)(soap_out_env_fault), soap, soap->fault); } /****************************************************************************** 函数名称: soap_serve_request() 函数描述: soap请求处理函数入口 输 入: soap – soap结构体地址 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_serve_request(SOAP_CONTEXT *soap) { U32 index = 0; PASSTHROUGH_RET ret = 0; if (soap == NULL || soap->tag[0] == ‘\0’) { return ERROR; } ret = onvif_serve_passthrough(soap); if (PASSTHROUGH_ERROR == ret) { return ERROR; } else if (PASSTHROUGH_SOAP_FAULT == ret) { SOAP_IF_FAIL_RET(soap_generate_fault(soap)); } else if (PASSTHROUGH_NOT_MATCH == ret) { for (index = 0; index < SOAP_TAG_NUM; index++) { if (NULL == g_soap_tag_handle[index].handle) { SOAP_IF_FAIL_RET(soap_fault(soap, “SOAP-ENV:Receiver”, “ter:ActionNotSupported”, NULL, NULL)); soap->error = SOAP_FAULT; SOAP_IF_FAIL_RET(soap_generate_fault(soap)); break; } if (soap_match_tag(soap->tag, g_soap_tag_handle[index].tag)) { if (g_soap_tag_handle[index].handle(soap)) { if (soap->fault == NULL) { soap_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", NULL, "error"); soap->error = SOAP_FAULT; } SOAP_IF_FAIL_RET(soap_generate_fault(soap)); } break; } } if (index >= SOAP_TAG_NUM) { SOAP_IF_FAIL_RET(soap_fault(soap, "SOAP-ENV:Receiver", "ter:ActionNotSupported", NULL, NULL)); soap->error = SOAP_FAULT; SOAP_IF_FAIL_RET(soap_generate_fault(soap)); } } /* UDP直接回复,HTTP在上一层回复 */ if (soap->use_udp == TRUE && soap->xml_buf.start != NULL && soap->xml_buf.start != soap->xml_buf.last) { return onvif_send_udp_packet(soap->sock, soap->in_ip, soap->sin_port, soap->xml_buf.start, (soap->xml_buf.last - soap->xml_buf.start)); } return OK; } LOCAL S32 soap_env_fault_handle(SOAP_CONTEXT *soap) { if (soap == NULL) { ONVIF_WARN(“soap == NULL.); return ERROR; } ONVIF_TRACE("SOAP-ENV:Fault handle."); /* do nothing and no response */ return OK; } /****************************************************************************** 函数名称: soap_tag_handle_add() 函数描述: 注册soap请求处理函数 输 入: tag – 请求tag handle -- 处理函数 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ void soap_tag_handle_add(char *tag, void *handle) { U32 index = 0; if ((NULL == tag) || (strlen(tag) >= 64) || (NULL == handle)) { ONVIF_ERROR(“soap handle add error, invalid arg.); return; } while ((index < SOAP_TAG_NUM) && (NULL != g_soap_tag_handle[index].handle)) { index++; } if (index >= SOAP_TAG_NUM) { ONVIF_ERROR(“soap handle add error, max support %d tags.”, SOAP_TAG_NUM); return; } snprintf(g_soap_tag_handle[index].tag, sizeof(g_soap_tag_handle[index].tag), “%s”, tag); g_soap_tag_handle[index].handle = handle; return; } /****************************************************************************** 函数名称: soap_tag_handle_init() 函数描述: 初始化soap请求处理函数 输 入: N/A 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ void soap_tag_handle_init() { U32 index = 0; for (index = 0; index < SOAP_TAG_NUM; index++) { memset(g_soap_tag_handle[index].tag, 0, sizeof(g_soap_tag_handle[index].tag)); g_soap_tag_handle[index].handle = NULL; } soap_tag_handle_add(“SOAP-ENV:Fault”, soap_env_fault_handle); return; } /****************************************************************************** 整体模块结构 初始化:调用soap_tag_handle_init初始化路由表。 创建上下文:new_soap创建一个新的SOAP上下文。 初始化上下文:soap_init初始化或重置上下文。 解析请求:由外部函数(如soap_parse_request)解析请求,填充上下文(如设置tag)。 处理请求:调用soap_serve_request,根据标签查找处理函数并执行。 错误处理:若处理出错,使用soap_fault设置错误信息,然后soap_generate_fault生成错误报文。 发送响应:如果是UDP,直接发送;如果是HTTP,由上层发送。 释放资源:调用free_soap释放上下文。 对外接口 soap_serve_request:请求处理入口。 soap_fault:业务函数用于报告错误。 soap_tag_handle_add:业务模块注册处理函数。 soap_tag_handle_init:模块初始化(系统启动调用)。 // Copyright © 2018-2018 TP-Link Systems Inc. Filename: soap_parse.c Version: 1.0 Description: soap 报文解析函数 Author: liyijieliyijie@tp-link.com.cn Date: 2018-11-29 ******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include “soap_global.h” #include “soap_parse.h” LOCAL const SOAP_CODE_MAP g_xml_entity_table[] = { {(S32)‘&’, “amp”}, {(S32)‘'’, “apos”}, {(S32)‘>’, “gt”}, {(S32)‘<’, “lt”}, {(S32)‘"’, “quot”} }; /* abbr表示namespace的缩写,num表示该namespace在G_TP_NAMESPACE_LIST中的序号 */ struct recv_namespace_t { unsigned char num; char abbr[MAX_NAMESPACE_ABBR_LEN]; }; struct recv_namespaces { unsigned char ns_count; struct recv_namespace_t recv_namespace_list[MAX_TP_NAME_SPACE_COUNT]; }; LOCAL struct recv_namespaces g_recv_ns = {0}; LOCAL BOOL g_need_get_global_namespace = FALSE; LOCAL BOOL g_need_get_tag_namespace = FALSE; LOCAL int g_tag_namespace = -1; /**************************************************************************** Function : soap_ipv4_ntop Description: 将十进制形式的IPv4地址换为字符串形式 Input : ip_str : IPv4地址字符串形式指针 ip_dec : IPv4地址十进制形式指针 str_len : IPv4地址缓存长度 Output : N/A Return : 成功返回OK,出错返回ERROR ****************************************************************************/ STATUS soap_ipv4_ntop(u_int32 ip_dec, char *ip_str, u_int32 str_len) { struct in_addr in_addr; if (!ip_str || str_len < 8) { return ERROR; } in_addr.s_addr = htonl(ip_dec); if (inet_ntop(AF_INET, &in_addr, ip_str, str_len) == NULL) { return ERROR; } return OK; } /****************************************************************************** 函数名称: soap_match_tag() 函数描述: 匹配soap tag 输 入: str – 需要比对的字符串 tag -- 输入的tag 输 出: N/A 返 回 值: TRUE/FALSE ******************************************************************************/ BOOL soap_match_tag(char *str, const char *tag) { char *ptr_str = NULL; char *ptr_tag = NULL; S32 i = 0; if (str == NULL || tag == NULL) { return FALSE; } ptr_tag = strchr(tag, '😂; ptr_str = strchr(str, '😂; /* 当tag和str中都有’:',将两个字符串分成:前和:后,作两次比较 */ if (ptr_tag != NULL && ptr_str != NULL) { char *prev_str = str; while (prev_str && *prev_str == '/') { prev_str++; } /*比较:前的部分*/ if (!prev_str || strncasecmp((const char *)prev_str, tag, ptr_tag - tag) != 0 || strncasecmp((const char *)prev_str, tag, ptr_str - prev_str) != 0) { return FALSE; } /*继续比较:后的部分*/ ptr_str = ptr_str + 1; ptr_tag = ptr_tag + 1; } /* 当tag和str中都没有’:‘,完整比对两个字符串 */ else if (ptr_tag == NULL && ptr_str == NULL) { ptr_str = str; ptr_tag = (char )tag; } / 当tag和str中有一个字符串有’:‘,该字符串跳过’:',然后再进行比对 */ else { ptr_tag = (ptr_tag == NULL) ? (char *)tag : ptr_tag + 1; ptr_str = (ptr_str == NULL) ? str : ptr_str + 1; } while (ptr_str && *ptr_str == ‘/’) { ptr_str++; } if (!ptr_str || !ptr_tag) { return FALSE; } for (i = 0; i < strlen(ptr_tag); i++) { if (!ptr_str || *ptr_str == ‘\0’ || TOLOWER(*ptr_str) != TOLOWER(ptr_tag[i])) { return FALSE; } ptr_str++; } if (!ptr_str || *ptr_str != ‘\0’) { return FALSE; } return TRUE; } /****************************************************************************** 函数名称: soap_get_char() 函数描述: 从需要解析的xml字串中从获取一个字符 输 入: str – xml字串地址 输 出: N/A 返 回 值: 获取的字符 ******************************************************************************/ S32 soap_get_char(char **str) { S32 ch; const char **ps; if (str == NULL || *str == NULL) { return EOF; } ps = (const char **)str; if ((ch = (*ps)[0]) != 0) { (*ps)++; return ch; } return EOF; } /****************************************************************************** 函数名称: soap_add_char() 函数描述: 将一个字符加入指定buf中 输 入: ch – 需要添加的字符 pch -- buf最后一个有效字符的地址 buf -- 指定buf size -- 指定buf的大小 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_add_char(S32 ch, char **pch, char *buf, S32 size) { if (pch == NULL || *pch == NULL || buf == NULL) { return ERROR; } if (*pch >= buf + size - 1) { return ERROR; } *(*pch)++ = ch & 0xff; return OK; } /****************************************************************************** 函数名称: soap_get_entity_value() 函数描述: 将xml字串中的义字符串换成实际字符 输 入: entity – 义字符串 输 出: N/A 返 回 值: 获取的字符 ******************************************************************************/ LOCAL S32 soap_get_entity_value(const char *entity) { U32 index = 0; U32 size = sizeof(g_xml_entity_table) / sizeof(g_xml_entity_table[0]); if (NULL == entity) { return -1; } for (index = 0; index < size; index++) { if (0 == strncmp(g_xml_entity_table[index].str, entity, strlen(g_xml_entity_table[index].str))) { return g_xml_entity_table[index].code; } } return -1; } /****************************************************************************** 函数名称: soap_get_entity() 函数描述: 获取xml字串中的义字符串并换成实际字符 输 入: str – xml字串地址 输 出: N/A 返 回 值: 获取的字符 ******************************************************************************/ LOCAL S32 soap_get_entity(char **str) { S32 ch = 0; char *entptr = NULL; char entity[32] = {0}; if (str == NULL || *str == NULL) { return EOF; } entptr = entity; while ((ch = soap_get_char(str)) != EOF) { if (ch > 126 || (!isalnum(ch) && ch != ‘#’)) { break; } else if (entptr < entity + sizeof(entity) - 1) { *entptr++ = ch; } else { break; } } *entptr = ‘\0’; if (ch != ‘;’) { return EOF; } if (entity[0] == ‘#’) { if (entity[1] == ‘x’) { ch = strtol(entity + 2, NULL, 16); } else { ch = strtol(entity + 1, NULL, 10); } } else { ch = soap_get_entity_value(entity); } return ch; } /****************************************************************************** 函数名称: soap_get_tag() 函数描述: 获取xml字串中element tag 输 入: str_start – xml字串起始地址 xml_str_len -- xml字串长度 p -- 已经解析的xml字串地址 out_buf -- tag输出buf地址 out_buf_len -- tag输出buf大小 输 出: 获得的tag 返 回 值: 获得完整tag后的下一个字符 ******************************************************************************/ S32 soap_get_tag(char *str_start, S32 xml_str_len, char **p, char *out_buf, S32 out_buf_len) { S32 ch = 0; char *pch = out_buf; if (str_start == NULL || out_buf == NULL || *p < str_start || xml_str_len <= 0 || out_buf_len <= 0 || (*p - str_start) >= xml_str_len) { return EOF; } memset(out_buf, 0, out_buf_len); while ((*p - str_start) < xml_str_len) { ch = soap_get_char(p); if (ch == ‘<’) { pch = out_buf; while ((*p - str_start) < xml_str_len) { ch = soap_get_char(p); if (IS_WHITE_SPACE(ch) || ch == ‘>’ || (ch == ‘/’ && pch > out_buf)) { break; } else if (ch == ‘&’) { if ((ch = soap_get_entity(p)) == EOF) { return EOF; } } if(soap_add_char(ch, &pch, out_buf, out_buf_len)) { return EOF; } } pch[0] = '\0'; break; } } ONVIF_TRACE(“tag:%s”, out_buf); return ch; } int soap_rearrange_tag(const char *src_tag, char *dest_tag) { char *temp_ptr = NULL; int namespace_num = g_tag_namespace; struct recv_namespaces *recv_ns = &g_recv_ns; char tag_abbr[MAX_NAMESPACE_ABBR_LEN] = {0}; char temp_abbr[MAX_NAMESPACE_ABBR_LEN] = {0}; int i = 0; if (!src_tag || !dest_tag) { ONVIF_ERROR("!src_tag || !dest_tag"); return ERROR; } if (namespace_num == -1 && recv_ns->ns_count == 0) { ONVIF_DEBUG("No need to rearrange tag."); return OK; } /* 获取tag内自带的abbr */ temp_ptr = strchr(src_tag, ':'); if (temp_ptr) { snprintf(tag_abbr, temp_ptr - src_tag + 1, "%s", src_tag); temp_ptr++; } else { temp_ptr = (char *)src_tag; } /* 获取abbr,首先使用tag后面指定的namespace */ if (namespace_num != -1) { if(namespace_num < 0 || namespace_num >= MAX_TP_NAME_SPACE_COUNT || G_TP_NAMESPACE_LIST[namespace_num].namespace[0] == 0 || G_TP_NAMESPACE_LIST[namespace_num].namespace_abbr[0] == 0) { ONVIF_ERROR("Get local namespace abbr fail, namespace_num=%d", namespace_num); return ERROR; } snprintf(temp_abbr, MAX_NAMESPACE_ABBR_LEN, "%s", G_TP_NAMESPACE_LIST[namespace_num].namespace_abbr); } /* 其次从g_recv_ns中获取 */ else if (tag_abbr[0] != 0) { for (i = 0; i < recv_ns->ns_count && i < MAX_TP_NAME_SPACE_COUNT; ++i) { if (strcmp(tag_abbr, recv_ns->recv_namespace_list[i].abbr) == 0 && recv_ns->recv_namespace_list[i].num < MAX_TP_NAME_SPACE_COUNT) { snprintf(temp_abbr, MAX_NAMESPACE_ABBR_LEN, "%s", G_TP_NAMESPACE_LIST[recv_ns->recv_namespace_list[i].num].namespace_abbr); //如果命名空间相同,取最新的,防重名 } } } /* 如果通过上面两种方式未获取到namespace,则直接退出,不重组tag */ if (0 == temp_abbr[0]) { return OK; } memset(dest_tag, 0, LEN_TAG); snprintf(dest_tag, LEN_TAG, "%s:%s", temp_abbr, temp_ptr); ONVIF_DEBUG("Tag changes, %s -> %s", src_tag, dest_tag); return OK; } /* 如果abbr为NULL,表示需要获取形如的 namespace,返回值为http://www.onvif.org/ver10/device/wsdl在G_TP_NAMESPACE_LIST中的下标值; 如果abbr不为空,表示需要获取形如<s:Envelope xmlns:s=“http://www.w3.org/2003/05/soap-envelope”>的 namespace,将这里定义的缩写s传到abbr中,并返回http://www.w3.org/2003/05/soap-envelope在 G_TP_NAMESPACE_LIST中的下标值; 如果没有匹配到namespace,或者tag里的namespace与缩写和已有的一致,则返回-1 */ int soap_get_namespace(const char *attr_name, const char *attr_value, char *abbr) { int i = -1; if (!attr_name || !attr_value) { ONVIF_ERROR("!attr_name || !attr_value"); return -1; } /* 确认是否是namespace */ if (NULL == strstr(attr_name, "xmlns")) { ONVIF_ERROR("Not a namespace: %s", attr_name); return -1; } /* 获取abbr */ if (abbr) { memset(abbr, 0, MAX_NAMESPACE_ABBR_LEN); if (1 == sscanf(attr_name, "xmlns:%15s", abbr) && 0 < strlen(abbr)) { ONVIF_DEBUG("Get abbr=%s", abbr); } else { ONVIF_DEBUG("Get abbr fail, attr_name=%s", attr_name); abbr[0] = 0; } } /* 查找对应namespace的下标 */ for (i = 0; i < MAX_TP_NAME_SPACE_COUNT; ++i) { if (0 != G_TP_NAMESPACE_LIST[i].namespace[0] && 0 == strcmp(G_TP_NAMESPACE_LIST[i].namespace, attr_value)) { /* 如果获取的是local namespace,或者获取到的abbr与已有的不一致,那就直接返回 */ if (!abbr) { ONVIF_DEBUG("Find a local namespace-%s, ret-%d", attr_value, i); return i; } else if (0 != abbr[0]) { if (0 != strcmp(G_TP_NAMESPACE_LIST[i].namespace_abbr, abbr)) { ONVIF_DEBUG("Find a global namespace-%s(%s), ret-%d", attr_value, abbr, i); return i; } else { ONVIF_DEBUG("This global namespace(%s-%s) has already exist.", abbr, attr_value); return -1; } } else { ONVIF_DEBUG("Find a local namespace-%s, ret-%d", attr_value, i); return i; } } } ONVIF_DEBUG("Can not find this namespace:%s", attr_value); return -1; } /****************************************************************************** 函数名称: soap_parse_element_attr() 函数描述: Parse an element for any attributes 输 入: str_start – xml字串起始地址 buf_len -- xml字串长度 p -- 已经解析的xml字串地址 输 出: 获得的tag 返 回 值: 解析完所有attr后的下一个字符 ******************************************************************************/ S32 soap_parse_element_attr(char *str_start, S32 buf_len, char **p) { char attr_name[LEN_TAG] = {0}; char attr_value[LEN_INFO] = {0}; char *ptr = NULL; S32 ch = 0; S32 quote = 0; BOOL need_get_tag_namespace = FALSE; BOOL need_get_global_namespace = FALSE; int temp_abbr_num = -1; char temp_abbr[MAX_NAMESPACE_ABBR_LEN] = {0}; need_get_tag_namespace = g_need_get_tag_namespace; g_need_get_tag_namespace = FALSE; need_get_global_namespace = g_need_get_global_namespace; g_need_get_global_namespace = FALSE; if (str_start == NULL || p == NULL || *p == NULL) { return EOF; } while ((p - str_start) < buf_len) { ch = soap_get_char(p); / Skip leading whitespace */ if (IS_WHITE_SPACE(ch)) { continue; } if (ch == '/' || ch == '?') { quote = soap_get_char(p); if (quote != '>') { return EOF; } (*p)--; break; } else if (ch == '<') { return EOF; } else if (ch == '>') { break; } attr_name[0] = ch; if (ch == '\"' || ch == '\'') /* Name is in quotes, so get a quoted string */ { quote = ch; ptr = attr_name; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { return EOF; } } if(soap_add_char(ch, &ptr, attr_name, sizeof(attr_name))) { return EOF; } if (ch == quote) { break; } } } else { ptr = attr_name + 1; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (IS_WHITE_SPACE(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?') { break; } if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { return EOF; } } if(soap_add_char(ch, &ptr, attr_name, sizeof(attr_name))) { return EOF; } } } *ptr = '\0'; while ((*p - str_start) < buf_len && IS_WHITE_SPACE(ch)) { ch = soap_get_char(p); } if (ch != '=') { return EOF; } /* Read the attribute value */ while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (!IS_WHITE_SPACE(ch)) { break; } } if (ch == '\"' || ch == '\'') { quote = ch; ptr = attr_value; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == quote) { break; } if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { return EOF; } } if(soap_add_char(ch, &ptr, attr_value, sizeof(attr_value))) { return EOF; } } } else { attr_value[0] = ch; ptr = attr_value + 1; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (IS_WHITE_SPACE(ch) || ch == '=' || ch == '/' || ch == '>') { break; } if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { return EOF; } } if(soap_add_char(ch, &ptr, attr_value, sizeof(attr_value))) { return EOF; } } } *ptr = '\0'; if (need_get_tag_namespace || need_get_global_namespace) { ONVIF_DEBUG("attr_name=%s, attr_value=%s", attr_name, attr_value); temp_abbr_num = soap_get_namespace(attr_name, attr_value, temp_abbr); ONVIF_DEBUG("temp_abbr_num=%d", temp_abbr_num); /* 通过temp_abbr[0]是否为0来区分是local还是global的abbr */ if (need_get_tag_namespace && temp_abbr_num > 0 && temp_abbr[0] == 0) { g_tag_namespace = temp_abbr_num; ONVIF_DEBUG("g_tag_namespace=%d", temp_abbr_num); } else if (need_get_global_namespace && temp_abbr_num != -1 && g_recv_ns.ns_count < MAX_TP_NAME_SPACE_COUNT && temp_abbr[0] != 0) { g_recv_ns.recv_namespace_list[g_recv_ns.ns_count].num = temp_abbr_num; snprintf(g_recv_ns.recv_namespace_list[g_recv_ns.ns_count].abbr, MAX_NAMESPACE_ABBR_LEN, "%s", temp_abbr); ONVIF_DEBUG("Recv global ns, ns_count=%d, num=%d, abbr=%s", g_recv_ns.ns_count, g_recv_ns.recv_namespace_list[g_recv_ns.ns_count].num, g_recv_ns.recv_namespace_list[g_recv_ns.ns_count].abbr); g_recv_ns.ns_count++; } } /* process attribute */ //if (soap_check_namespace(attr_value) == FALSE) //{ // ONVIF_WARN("soap_check_namespace failed, attr is %s:%s", attr_name, attr_value); // return EOF; //} if (ch == '/' || ch == '?') { quote = soap_get_char(p); if (quote != '>') { return EOF; } (*p)--; break; } else if (ch == '>') { break; } } return ch; } /****************************************************************************** 函数名称: soap_parse_element_attr_out_len() 函数描述: Parse an element for any attributes 输 入: str_start – xml字串起始地址 buf_len -- xml字串长度 p -- 已经解析的xml字串地址 attr_num -- 想要从<>中获取的attr的个数 attr_in_name -- 二维数组,想要获取的attr的名字 name_str_len -- attr_in_name二维数组每个元素的长度 value_str_len -- attr_out_value二维数组每个元素的长度 输 出: attr_out_value – 二维数组,存放attr_in_name对应的属性值 返 回 值: 解析完所有attr后的下一个字符 参数示例: 例如,想要取出<tt:SimpleItem Value=“60” Name=“Sensitivity”/>中, attr “Value”、"Name"的值,则为本函数传入如下参数: int attr_num = 2, char attr_in_name[2][10] = {{“Value”}, {“Name”}}; char attr_out_buf[2][30] = {{0}, {0}}; int name_str_len = sizeof(attr_in_name[0]); int value_str_len = sizeof(attr_out_buf[0]); 调用: ch = soap_parse_element_attr_out_len(str_start, buf_len, p, attr_num, (char *)attr_in_name, name_str_len, (char *)attr_out_buf, value_str_len); ******************************************************************************/ S32 soap_parse_element_attr_out_len(char *str_start, S32 buf_len, char p, int attr_num, char attr_in_name, int name_str_len, char attr_out_value, int value_str_len) { char* attr_name = NULL; char* attr_value = NULL; char *ptr = NULL; S32 ch = 0; S32 quote = 0; S32 i = 0; char *pn = NULL; char *pv = NULL; if (str_start == NULL || p == NULL || *p == NULL || attr_num <= 0 || attr_in_name == NULL || name_str_len <= 0 || attr_out_value == NULL || value_str_len <= 0) { ONVIF_ERROR("param is error."); return EOF; } attr_name = SAFE_MALLOC(name_str_len); attr_value = SAFE_MALLOC(value_str_len); if (NULL == attr_name || NULL == attr_value) { ONVIF_ERROR("malloc fail"); goto error_end; } memset(attr_name, 0, name_str_len); memset(attr_value, 0, value_str_len); ONVIF_TRACE("before while"); while ((*p - str_start) < buf_len) { ch = soap_get_char(p); /* Skip leading whitespace */ if (IS_WHITE_SPACE(ch)) { continue; } if (ch == '/' || ch == '?') { quote = soap_get_char(p); if (quote != '>') { goto error_end; } (*p)--; break; } else if (ch == '<') { goto error_end; } else if (ch == '>') { break; } attr_name[0] = ch; if (ch == '\"' || ch == '\'') /* Name is in quotes, so get a quoted string */ { quote = ch; ptr = attr_name; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { goto error_end; } } if(soap_add_char(ch, &ptr, attr_name, name_str_len)) { goto error_end; } if (ch == quote) { break; } } } else { ptr = attr_name + 1; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (IS_WHITE_SPACE(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?') { break; } if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { goto error_end; } } if(soap_add_char(ch, &ptr, attr_name, name_str_len)) { //goto error_end; } } } *ptr = '\0'; while ((*p - str_start) < buf_len && IS_WHITE_SPACE(ch)) { ch = soap_get_char(p); } if (ch != '=') { goto error_end; } /* Read the attribute value */ while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (!IS_WHITE_SPACE(ch)) { break; } } if (ch == '\"' || ch == '\'') { quote = ch; ptr = attr_value; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == quote) { break; } if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { goto error_end; } } if(soap_add_char(ch, &ptr, attr_value, value_str_len)) { goto error_end; } } } else { attr_value[0] = ch; ptr = attr_value + 1; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (IS_WHITE_SPACE(ch) || ch == '=' || ch == '/' || ch == '>') { break; } if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { goto error_end; } } if(soap_add_char(ch, &ptr, attr_value, value_str_len)) { goto error_end; } } } *ptr = '\0'; ONVIF_TRACE("%s:%s", attr_name, attr_value); for (i = 0; i < attr_num; i++) { pn = attr_in_name + i * name_str_len; pv = attr_out_value + i * value_str_len; if (0 != *pv) { ONVIF_TRACE("%d has been set", i); continue; } ONVIF_TRACE("attr_name:\nwant:%s; get:%s", pn, attr_name); if (0 == strncmp(attr_name, pn, strlen(attr_name))) { strcpy(pv, attr_value); ONVIF_TRACE("%s:%s", pn, pv); memset(attr_name, 0, name_str_len); memset(attr_value, 0, value_str_len); break; } } /* process attribute */ //if (soap_check_namespace(attr_value) == FALSE) //{ // ONVIF_WARN("soap_check_namespace failed, attr is %s:%s", attr_name, attr_value); // return EOF; //} if (ch == '/' || ch == '?') { quote = soap_get_char(p); if (quote != '>') { goto error_end; } (*p)--; break; } else if (ch == '>') { break; } } ONVIF_FREE(attr_name); ONVIF_FREE(attr_value); return ch; error_end: ONVIF_FREE(attr_name); ONVIF_FREE(attr_value); return EOF; } /****************************************************************************** 函数名称: soap_parse_element_value() 函数描述: 解析element内容 输 入: str_start – xml字串起始地址 xml_str_len -- xml字串长度 p -- 已经解析的xml字串地址 ch -- 当前需要解析的下一个字符 out_buf -- tag输出buf地址 out_buf_len -- tag输出buf大小 输 出: element内容 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_parse_element_value(char *str_start, S32 buf_len, char **p, S32 ch, char *out_buf, S32 out_buf_len) { S32 tmp_ch = ch; char *pch = out_buf; if (str_start == NULL || buf_len <= 0 || p == NULL || *p == NULL || out_buf == NULL || out_buf_len <=0) { return ERROR; } if (IS_WHITE_SPACE(tmp_ch)) { tmp_ch = soap_parse_element_attr(str_start, buf_len, p); /* parse attribute */ if (tmp_ch == EOF) { ONVIF_WARN(“soap_parse_element_attr error.); return ERROR; } } if (tmp_ch == ‘/’) { tmp_ch = soap_get_char(p); if (tmp_ch != ‘>’) { ONVIF_WARN(“should be '>'(%d) but is %d.”, (S32)‘>’, tmp_ch); return ERROR; } return OK; } else if (tmp_ch == ‘>’) { while ((*p - str_start) < buf_len) { tmp_ch = soap_get_char(p); if (tmp_ch == ‘<’) { (*p)–; break; } else if (tmp_ch == ‘&’) { if ((tmp_ch = soap_get_entity(p)) == EOF) { ONVIF_WARN(“soap_get_entity error.); return ERROR; } } if(soap_add_char(tmp_ch, &pch, out_buf, out_buf_len)) { ONVIF_WARN("soap_add_char failed."); return ERROR; } } pch[0] = '\0'; } else { ONVIF_WARN(“should be '>'(%d) but is %d.”, (S32)‘>’, tmp_ch); return ERROR; } return OK; } /****************************************************************************** 函数名称: soap_parse_header_element() 函数描述: 解析所有头部元素,并做相应处理 输 入: soap – soap结构体地址 tag -- 头部元素tag str_start -- xml字串起始地址 buf_len -- xml字串长度 p -- 已经解析的xml字串地址 ch -- 当前需要解析的下一个字符 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ LOCAL S32 soap_parse_header_element(SOAP_CONTEXT *soap, char *tag, char *str_start, S32 buf_len, char **p, S32 ch) { char charbuf[LEN_INFO] = {0}; char tag_rearrange[LEN_TAG] = {0}; char *p1 = NULL; if (soap == NULL || tag == NULL || str_start == NULL || buf_len <= 0 || p == NULL || *p == NULL) { return ERROR; } p1 = *p; g_tag_namespace = -1; g_need_get_global_namespace = TRUE; g_need_get_tag_namespace = TRUE; if (OK != soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { return ERROR; } ONVIF_TRACE(“%s: %s”, tag, charbuf); if (charbuf[0] == ‘\0’) { return OK; } /* 根据命名空间跟换tag 如: request中Envelope 有内容:xmlns:a=“http://www.w3.org/2005/08/addressing” header中有: <a:MessageID>urn:uuid:7f52d7e1-63c4-4124-943c-c24d4825f15d</a:MessageID> 获取的tag为 a:MessageID 根据本地G_TP_NAMESPACE_LIST中的命名空间:{“wsa5”, “http://www.w3.org/2005/08/addressing”} 替换tag为 wsa5:MessageID reponse中Envelope 有内容:xmlns:wsa5=“http://www.w3.org/2005/08/addressing” header中有: wsa5:MessageIDurn:uuid:7f52d7e1-63c4-4124-943c-c24d4825f15d</wsa5:MessageID> */ soap_rearrange_tag(tag, tag_rearrange); ONVIF_TRACE(“[%s]: %s”, tag_rearrange, charbuf); if (TRUE == soap_match_tag(tag_rearrange, “wsa:MessageID”)) { snprintf(soap->header.wsa_msg_id, sizeof(soap->header.wsa_msg_id), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag_rearrange, “wsa:RelatesTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Relationship”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa_relates_to, sizeof(soap->header.wsa_relates_to), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa:From”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa_from_addr, sizeof(soap->header.wsa_from_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa:ReplyTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa_reply_to_addr, sizeof(soap->header.wsa_reply_to_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa:FaultTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa_fault_to_addr, sizeof(soap->header.wsa_fault_to_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa:To”)) { snprintf(soap->header.wsa_to, sizeof(soap->header.wsa_to), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag_rearrange, “wsa:Action”)) { snprintf(soap->header.wsa_action, sizeof(soap->header.wsa_action), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag_rearrange, “wsdd:AppSequence”)) { snprintf(soap->header.wsdd_app_sequence, sizeof(soap->header.wsdd_app_sequence), “%s”, charbuf); } else if (TRUE == soap_match_tag(tag_rearrange, “wsa5:MessageID”)) { snprintf(soap->header.wsa5_msg_id, sizeof(soap->header.wsa5_msg_id), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag_rearrange, “wsa5:RelatesTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “RelatesToType”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa5_relates_to, sizeof(soap->header.wsa5_relates_to), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa5:From”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa5_from_addr, sizeof(soap->header.wsa5_from_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa5:ReplyTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa5_reply_to_addr, sizeof(soap->header.wsa5_reply_to_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa5:FaultTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf))) { snprintf(soap->header.wsa5_fault_to_addr, sizeof(soap->header.wsa5_fault_to_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag_rearrange, “wsa5:To”)) { snprintf(soap->header.wsa5_to, sizeof(soap->header.wsa5_to), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag_rearrange, “wsa5:Action”)) { snprintf(soap->header.wsa5_action, sizeof(soap->header.wsa5_action), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag, “Username”)) { snprintf(soap->header.username, sizeof(soap->header.username), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag, “Password”)) { soap_parse_element_attr_out_len(str_start, buf_len, &p1, 1, “Type”, LEN_IFNAME, (char *)soap->header.password_type, sizeof(soap->header.password_type)); snprintf(soap->header.password, sizeof(soap->header.password), "%s", charbuf); } else if(TRUE == soap_match_tag(tag, “Nonce”)) { snprintf(soap->header.nonce, sizeof(soap->header.nonce), “%s”, charbuf); } else if(TRUE == soap_match_tag(tag, “Created”)) { snprintf(soap->header.created, sizeof(soap->header.created), “%s”, charbuf); } /* 下面的内容是为了适配onvif device manager的异常tag { / else if (TRUE == soap_match_tag(tag, “MessageID”)) { if (‘\0’ == soap->header.wsa_msg_id[0]) { snprintf(soap->header.wsa_msg_id, sizeof(soap->header.wsa_msg_id), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag, “ReplyTo”)) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) != EOF && TRUE == soap_match_tag(charbuf, “Address”) && OK == soap_parse_element_value(str_start, buf_len, p, ch, charbuf, sizeof(charbuf)) && ‘\0’ == soap->header.wsa_reply_to_addr[0]) { snprintf(soap->header.wsa_reply_to_addr, sizeof(soap->header.wsa_reply_to_addr), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag, “To”)) { if (‘\0’ == soap->header.wsa_to[0]) { snprintf(soap->header.wsa_to, sizeof(soap->header.wsa_to), “%s”, charbuf); } } else if(TRUE == soap_match_tag(tag, “Action”)) { if (‘\0’ == soap->header.wsa_action[0]) { snprintf(soap->header.wsa_action, sizeof(soap->header.wsa_action), “%s”, charbuf); } } / 适配onvif device manager的异常tag end} */ return OK; } /****************************************************************************** 函数名称: soap_xml_parse() 函数描述: xml字串解析函数 输 入: soap – soap结构体地址 xml_str -- xml字串起始地址 buf_len -- xml字串长度 输 出: N/A 返 回 值: ERROR/OK ******************************************************************************/ S32 soap_xml_parse(SOAP_CONTEXT *soap, char **xml_str, S32 buf_len) { BOOL request_have_header = FALSE; S32 ch = 0; char charbuf[4 * LEN_INFO] = {0}; char *str_start = NULL; char **p = xml_str; if (soap == NULL || xml_str == NULL || *xml_str == NULL || buf_len <= 0) { ONVIF_WARN(“soap == NULL || xml_str == NULL || buf_len <= 0.); return ERROR; } str_start = *xml_str; memset(&g_recv_ns, 0, sizeof(struct recv_namespaces)); /* onvif device manager发送的probe中不包含version行,导致设备探测失败; 当前也没有对version行进行处理,因此参考slp,不对version进行处理,先 去除这部分内容,从Envelope开始处理 */ // char pch = charbuf; #if 0 / parse version line */ while ((p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == ‘<’) { pch = charbuf; ch = soap_get_char(p); if (ch == ‘?’) { / macth version line */ if(soap_add_char(ch, &pch, charbuf, sizeof(charbuf))) { goto error_parse; } while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == '>' && pch > charbuf && pch[-1] == '?') { break; } else if (ch == '&') { if ((ch = soap_get_entity(p)) == EOF) { return EOF; } } if(soap_add_char(ch, &pch, charbuf, sizeof(charbuf))) { goto error_parse; } } if (ch != '>') { goto error_parse; } /* get version line, to do something */ pch[0] = '\0'; ONVIF_TRACE("version line: <%s>", charbuf); break; } else { continue; } } } #endif /* parse Envelope, request must have Envelope */ while ((*p - str_start) < buf_len) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) == EOF) { goto error_parse; } if (TRUE == soap_match_tag(charbuf, "Envelope")) { break; } } /* start parse Envelope attribute / if (IS_WHITE_SPACE(ch)) { g_need_get_global_namespace = TRUE; ch = soap_parse_element_attr(str_start, buf_len, p); / parse attribute */ if (ch == EOF) { goto error_parse; } } while ((*p - str_start) < buf_len) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) == EOF) { goto error_parse; } if (TRUE == soap_match_tag(charbuf, "Header") || TRUE == soap_match_tag(charbuf, "Body")) { break; } } soap->has_header = FALSE; /* parse Header, request maybe have Header / if (TRUE == soap_match_tag(charbuf, “Header”)) { request_have_header = TRUE; / parse Header value / / start parse Envelope attribute / if (IS_WHITE_SPACE(ch)) { ch = soap_parse_element_attr(str_start, buf_len, p); / parse attribute */ if (ch == EOF) { goto error_parse; } } if (ch == '/') { ch = soap_get_char(p); if (ch != '>') { goto error_parse; } goto parse_body; } soap->has_header = TRUE; while ((*p - str_start) < buf_len) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) == EOF) { goto error_parse; } if (charbuf[0] == '/') { if (TRUE == soap_match_tag(charbuf, "Header")) { /* end of Header */ ONVIF_TRACE("end of Header"); break; } else { continue; } } if (ERROR == soap_parse_header_element(soap, charbuf, str_start, buf_len, p, ch)) { goto error_parse; } } } else { request_have_header = FALSE; } parse_body: /* parse Body, request must have Body */ if (request_have_header == TRUE) { while ((*p - str_start) < buf_len) { if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) == EOF) { goto error_parse; } if (TRUE == soap_match_tag(charbuf, "Body")) { break; } } } if (IS_WHITE_SPACE(ch)) { g_need_get_global_namespace = TRUE; ch = soap_parse_element_attr(str_start, buf_len, p); /* parse attribute */ if (ch == EOF) { goto error_parse; } } if (ch == '/') { ch = soap_get_char(p); if (ch != '>') { goto error_parse; } goto end_parse; } /* parse Body value */ if ((ch = soap_get_tag(str_start, buf_len, p, charbuf, sizeof(charbuf))) == EOF) { goto error_parse; } snprintf(soap->tag, sizeof(soap->tag), "%s", charbuf); ONVIF_TRACE("get soap->tag: %s", soap->tag); g_tag_namespace = -1; if (IS_WHITE_SPACE(ch)) { g_need_get_global_namespace = TRUE; g_need_get_tag_namespace = TRUE; ch = soap_parse_element_attr(str_start, buf_len, p); /* parse attribute */ if (ch == EOF) { goto error_parse; } } if (ch == '/') { ch = soap_get_char(p); if (ch != '>') { goto error_parse; } soap->request_begin = NULL; soap->request_end = NULL; } else if (ch == '>') { soap->request_begin = *p; while ((*p - str_start) < buf_len) { ch = soap_get_char(p); if (ch == '/' && 0 == strncmp(*p, soap->tag, strlen(soap->tag))) { while (**p != '<') { (*p)--; } soap->request_end = *p; break; } } } else { goto error_parse; } soap_rearrange_tag(charbuf, soap->tag); end_parse: return OK; error_parse: return ERROR; } ——这个是soap.c和soap_parse.c文件,并注意Digest认证的验证函数直接写在onvif_srv.c就行,重新回答前面的Digest认证的实现的问题
09-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值