#!/usr/bin/perl # # Open Fetion Perl Version # By Shikai Chen ( csk@live.com ) # Please visit my website http://www.csksoft.net # USAGE: # # REQUIREMENTS: # ----------------------------- # PERL interpreter # Curl # shell with utf-8 encoding # Date Revision #------------------------------- # June.28th 2009 0.1 # LICENSE GPL # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # use Digest::MD5 qw(md5 md5_hex); use Socket; # Global Config my $FETION_USER_AGENT = "IIC2.0/PC 2.3.0230"; my $FETION_DOMAIN_URL = "fetion.com.cn"; my $FETION_CONFIG_URL = "https://nav.fetion.com.cn/nav/getsystemconfig.aspx"; my $FETION_CONF_REQUEST = ""; my $FETION_SSIAPP_POST = "mobileno=%s&pwd=%s"; my $FETION_SIPC_LOGIN_P1 = ""; my $FETION_SIPC_LOGIN_R1 = "R %s SIP-C/2.0\r\nF: %s\r\nI: 1\r\nQ: 1 R\r\nL: %s\r\n\r\n"; my $FETION_SIPC_LOGIN_P2 = ""; my $FETION_SIPC_LOGIN_R2 = "R %s SIP-C/2.0\r\nF: %s\r\nI: 1\r\nQ: 2 R\r\nA: Digest response=\"%s\",cnonce=\"%s\"\r\nL: %s\r\n\r\n"; my $FETION_SIPC_SENDSMS = "M %s SIP-C/2.0\r\nF: %s\r\nI: 2\r\nQ: 1 M\r\nT: tel:%s\r\nN: SendSMS\r\nL: %s\r\n\r\n"; my $FETION_SIPC_LOGOUT = "R %s SIP-C/2.0\r\nF: %s\r\nI: 1 \r\nQ: 3 R\r\nX: 0\r\n\r\n"; # Global Data my $FETION_SSI_URL = "https://uid.fetion.com.cn/ssiportal/SSIAppSignIn.aspx"; my $FETION_SIPC_ADDRESS = "221.176.31.33:8080"; my $g_isverbose = 0; my $g_fetion_num = ""; my $g_mobile_num = ""; my $g_passwd = ""; my $g_cnonce = ""; my $g_nonce = ""; #TODO: proxy support not included # # Functions # UNUSED # Generate GUID String sub guid { local($randomseed); local($hashed_id); $randomseed = rand(1000); $hashed_id = uc(md5_hex time()."$randomseed"); $hashed_id = '{'.substr($hashed_id,0,8).'-' .substr($hashed_id,8,4).'-' .substr($hashed_id,12,4).'-' .substr($hashed_id,16,4).'-' .substr($hashed_id,20,12).'}'; } # Debug Output sub debug_print { if ( $g_isverbose == 1) { print @_[0]."\n"; } } ############################################################# ## HELP FUNCTIONS # ~~~~~~~~~~~~~~~~~ # SIPC Socket # ~~~~~~~~~~~~~~~~~ # Init the sipc socket and connect to the target # # sipc_connect( addr, port ) sub sipc_connect { local $dest; local $exec_ans = -1; $dest = sockaddr_in( @_[1], inet_aton( @_[0] ) ); if ( socket( SIPC_CLIENT, AF_INET, SOCK_STREAM, SOL_TCP)) { setsockopt( SIPC_CLIENT, SOL_SOCKET, SO_SNDTIMEO, pack('LL', 15,0) ); setsockopt( SIPC_CLIENT, SOL_SOCKET, SO_RCVTIMEO, pack('LL', 15,0) ); if ( connect( SIPC_CLIENT, $dest ) ) { $exec_ans = 0; } else { close SIPC_CLIENT; } } return $exec_ans; } #Close the sipc socket connection sub sipc_close { close SIPC_CLIENT; } #Read data from the sipc socket # # RETURN: the data sub sipc_read { local $read_buffer; local $recv_data; local $recv_len; do { $recv_len = sysread(SIPC_CLIENT, $recv_data, 4); $read_buffer .= $recv_data; }while( index($read_buffer, "\r\n\r\n")== -1 ); if ( $read_buffer =~ /L: ([0-9]+)/i ) { local $data_len = $1; $recv_len = sysread(SIPC_CLIENT, $recv_data, $data_len); #TODO: the actually received data length is not verified. $read_buffer .= $recv_data; } return $read_buffer; } #Write data to the spic socket # #spic_write( data ) # RETURN: length of the data been sent sub sipc_write { local $sent_size; $sent_size = syswrite(SIPC_CLIENT, @_[0], length(@_[0])); } #Send sipc request and receive the response #sipc_request(request_data) # RETURN: response data sub sipc_request { &sipc_write( @_[0] ); #TODO: check whether the write operation works return &sipc_read(); } ################################ # ~~~~~~~~~~~~~~~~~ # CURL Functions # ~~~~~~~~~~~~~~~~~ # Post HTTP data via curl # @url url # @post data to post # return HTTP response # curl_http_post($url, $post = null) sub curl_http_post { local $curl_cmd; local $curl_response; $curl_cmd = "curl -s -k -m 20"; $curl_cmd .= " -A \"$FETION_USER_AGENT\""; #set user agent if ( @_[1] ne "" ) #postdata { $curl_cmd .= " -d \@\-"; } $curl_cmd = "echo -n ".quotemeta(@_[1])."|".$curl_cmd." @_[0]"; $response = `$curl_cmd`; if ($? != 0) { $response = ""; #execute curl failed, clear the response data } return $response; #return the response } ########################################################### # Fetion Procotol handled here #Retrieve the config XML of the given fetion account # #fetion_get_config(mobile_num) #RETURN: config xml sub fetion_get_config { local $request_string; local $returndata; $request_string = sprintf($FETION_CONF_REQUEST, @_[0]); $returndata = &curl_http_post($FETION_CONFIG_URL, $request_string); } #Retrieve the URL to query SIP # #fetion_ssiapp_addr( conf_xml ) sub fetion_ssiapp_addr { local $matched_string; if ( @_[0] =~ /([^<]*)<\/ssi-app-sign-in>/i) { $matched_string = $1; }else { $matched_string = ""; } return $matched_string; } #Retrieve the SIPC login address # #fetion_sipc_address( conf_xml ) sub fetion_sipc_address { local $matched_string; if ( @_[0] =~ /([^<]*)<\/sipc-proxy>/i) { $matched_string = $1; }else { $matched_string = ""; } return $matched_string; } #Pefrom SSIAPP login action #fetion_ssiapp_login( ssi_url, mobile_num, passwd ) # RETURN: login return xml sub fetion_ssiapp_login { local $request_string; local $returndata; $request_string = sprintf($FETION_SSIAPP_POST, @_[1], @_[2]); $returndata = &curl_http_post(@_[0], $request_string); } #Get the fetion account number #fetion_get_account_num ( ssiapp_login_return_xml) # sub fetion_get_account_num { local $matched_string = ""; if ( @_[0] =~ /