随笔-348  评论-598  文章-0  trackbacks-0
飞信免费短信接口:http://sms.api.bz/fetion.php?username=13800138000&password=123456&sendto=13800138000&message=短信内容,号码和密码请自行替换
#!/usr/bin/perl
#
# Open Fetion Perl Version
# By Shikai Chen ( csk@live.com )
# Please visit my website http://www.csksoft.net

# USAGE: <this_script> <your_mobile_number> <password> <target_number> <message to send>

# 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  = "<config><user mobile-no=\"%s\" /><client type=\"PC\" version=\"2.3.0230\" platform=\"W5.1\" /><servers version=\"0\" /><service-no version=\"12\" /><parameters version=\"15\" /><hints version=\"13\" /><http-applications version=\"14\" /><client-config version=\"17\" /></config>";
my $FETION_SSIAPP_POST   = "mobileno=%s&pwd=%s";
my $FETION_SIPC_LOGIN_P1 = "<args><device type=\"PC\" version=\"6\" client-version=\"2.3.0230\" /><caps value=\"simple-im;im-session;temp-group\" /><events value=\"contact;permission;system-message\" /><user-info attributes=\"all\" /><presence><basic value=\"400\" desc=\"\" /></presence></args>";
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 = "<args><device type=\"PC\" version=\"6\" client-version=\"2.3.0230\" /><caps value=\"simple-im;im-session;temp-group\" /><events value=\"contact;permission;system-message\" /><user-info attributes=\"all\" /><presence><basic value=\"400\" desc=\"\" /></presence></args>";
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;
  }
whileindex($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>([^<]*)<\/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>([^<]*)<\/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=~ /<user uri=\"sip:([0-9]+)\@fetion.com.cn;p=[0-9]+\"/i )
  {
    
$matched_string = $1;
  }

  
return $matched_string;
}

#Generate the disgest info for the secondary SIPC login
sub fetion_sipc_gen_digest
{
  
$g_cnonce = uc(md5_hex rand(1000));
  
  
local $key = md5("$g_fetion_num:$FETION_DOMAIN_URL:$g_passwd");
  
local $h1  = uc(md5_hex( "$key:$g_nonce:$g_cnonce" ));
  
local $h2  = uc(md5_hex( "REGISTER:$g_fetion_num"  ));
  
local $finalans = uc(md5_hex( "$h1:$g_nonce:$h2" ));
  
return $finalans;
}

#Pefrom SIPC login
#fetion_sip_login() 

sub fetion_sipc_login
{
  
local $login_request;
  
local $login_response;
  
if ($g_fetion_num eq ""
  {
    
return -1;
  }

  
$login_request = sprintf($FETION_SIPC_LOGIN_R1, $FETION_DOMAIN_URL, $g_fetion_num, length($FETION_SIPC_LOGIN_P1));
  
$login_request .= $FETION_SIPC_LOGIN_P1;

  debug_print 
"Request#1\n".$login_request."\n";

  
$login_response = &sipc_request( $login_request );

  debug_print 
"Response#1\n".$login_response."\n";

  
if ( $login_response eq "" )
  {
    
return -1;
  }

  
if ( $login_response =~ /nonce=\"([^\"]{32})\"/i )
  {
    $g_nonce = $1;  
    debug_print 
"g_nonce:".$g_nonce."\n";
  }else
  {
    return -2;
  }

  $login_request = sprintf($FETION_SIPC_LOGIN_R2, $FETION_DOMAIN_URL, $g_fetion_num, &fetion_sipc_gen_digest(), $g_cnonce ,length($FETION_SIPC_LOGIN_P2));
  $login_request .= $FETION_SIPC_LOGIN_P2;

  debug_print 
"Request#2:\n".$login_request."\n";

  
$login_response = &sipc_request( $login_request );

  debug_print 
"Response#2:\n".$login_response."\n";
  
if ( $login_response =~ /200 OK/ )
  {
    
print "Login OK\n";
    
return 0;
  }

  
return -1;
}

#Send the required text to the specified mobile
#fetion_sendSMS( target_num, text )
#NOTE: always assumes the text is encoded using UTF-8.

sub fetion_sendSMS
{
  
local $sms_request = sprintf($FETION_SIPC_SENDSMS,$FETION_DOMAIN_URL, $g_fetion_num, @_[0], length(@_[1])); 
  
$sms_request .= @_[1];

  debug_print 
"SendSMS Request:\n".$sms_request."\n";
  
local $sipc_response = &sipc_request($sms_request);
  debug_print 
"SendSMS Response:\n".$sipc_response."\n";
  
  
if ( $sipc_response =~ /Send SMS OK/ )
  {
    
print "Send SMS succeed\n";
    
return 0;
  }
  
return -1;
}

#Logout Fetion
#

sub fetion_sipc_logout
{
  
  
local $logout_request = sprintf($FETION_SIPC_LOGOUT,$FETION_DOMAIN_URL, $g_fetion_num);
  debug_print 
"Send Logout Request:\n".$logout_request."\n";
  
local $sipc_response = &sipc_request($logout_request);
  debug_print 
"Logout Response:\n".$sipc_response."\n"
}








##################################################
#


sub fetion_verbose
{
  
$g_isverbose = 1;

}

# INIT the Fetion Lib
# fetion_init( mobile_num, passwd)

sub fetion_init
{
  
$g_mobile_num = @_[0];
  
$g_passwd = @_[1];

  
print "Retrieving the config xml\n";
  
$config_xml =&fetion_get_config( $g_mobile_num );
  
  
&debug_print ("The XML:\n".$config_xml."\n");
  
if ($config_xml eq "")
  {
    
print "cannot retrieve the config xml exit\n";
    
return -1;
  }

  
print "Retrieving the SSIAPP URL\n";
  
$FETION_SSI_URL = &fetion_ssiapp_addr($config_xml);
  
&debug_print ("The URL: ".$FETION_SSI_URL."\n");

  
if ($FETION_SSI_URL eq "")
  {
    
print "cannot get the ssiapp url exit\n";
    
return -1;
  }     

  
print "Retrieving the SIPC Address\n";
  
$FETION_SIPC_ADDRESS = &fetion_sipc_address($config_xml);
  
&debug_print ("The Address: ".$FETION_SIPC_ADDRESS."\n");

  
if ($FETION_SIPC_ADDRESS eq "")
  {
    
print "cannot get the address exit\n";
    
return -1;
  } 

  
print "Trying to get the fetion number of the current account\n";
  
$g_fetion_num = &fetion_get_account_num(&fetion_ssiapp_login($FETION_SSI_URL, $g_mobile_num, $g_passwd));
  
&debug_print ("The Fetion Number: ".$g_fetion_num."\n");

  
if ($g_fetion_num eq "")
  {
    
print "cannot get the fetion number exit\n";
    
return -1;
  } 

  
print "Connecting to the SIPC via TCP socket\n";
  
local @addr_info = split(":", $FETION_SIPC_ADDRESS);
  
  
if ( &sipc_connect( @addr_info[0], @addr_info[1] ) != 0)
  {
    
print "Cannot connect to the address:".$FETION_SIPC_ADDRESS."\n";
    
&debug_print ("Reason: ".$!."\n");
  }
  
return 0
}


# Release the Fetion Lib

sub fetion_close
{
  
&sipc_close;
}
#############################################################################


sub main
{
  
if (&fetion_init( @ARGV[0], @ARGV[1] ) != 0)
  {
    
return -1;
  }

  
if (&fetion_sipc_login() != 0 )
  {
    
return -1;
  }

  
if (&fetion_sendSMS( @ARGV[2], @ARGV[3]) != 0)
  {
    
return -1;
  }


  
&fetion_sipc_logout();
  
&fetion_close();
  
return 0;
}

&main;


---------------------------------------------------------
专注移动开发

Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
posted on 2010-05-09 18:05 TiGERTiAN 阅读(976) 评论(0)  编辑  收藏 所属分类: Perl/Python

只有注册用户登录后才能发表评论。


网站导航: