From c5ddee94aa68a459b86eaf3e8b5c86e9c7d24bcf Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Mon, 7 Feb 2011 20:20:22 +0100 Subject: [PATCH] added sms contact form for my webblog --- sms_contact/.gitignore | 1 + sms_contact/blacklist.csv | 1 + sms_contact/blacklist.php | 32 ++++ sms_contact/index.php | 86 +++++++++ sms_contact/js/md5.js | 9 + sms_contact/js/sms.js | 33 ++++ sms_contact/sipgateAPI.php | 267 +++++++++++++++++++++++++++ sms_contact/sipgateAPI_Exception.php | 31 ++++ 8 files changed, 460 insertions(+) create mode 100644 sms_contact/.gitignore create mode 100644 sms_contact/blacklist.csv create mode 100644 sms_contact/blacklist.php create mode 100644 sms_contact/index.php create mode 100644 sms_contact/js/md5.js create mode 100644 sms_contact/js/sms.js create mode 100644 sms_contact/sipgateAPI.php create mode 100644 sms_contact/sipgateAPI_Exception.php diff --git a/sms_contact/.gitignore b/sms_contact/.gitignore new file mode 100644 index 0000000..4f4773f --- /dev/null +++ b/sms_contact/.gitignore @@ -0,0 +1 @@ +config.php diff --git a/sms_contact/blacklist.csv b/sms_contact/blacklist.csv new file mode 100644 index 0000000..78b01c8 --- /dev/null +++ b/sms_contact/blacklist.csv @@ -0,0 +1 @@ +127.0.0.1 1297105523 diff --git a/sms_contact/blacklist.php b/sms_contact/blacklist.php new file mode 100644 index 0000000..468b849 --- /dev/null +++ b/sms_contact/blacklist.php @@ -0,0 +1,32 @@ + diff --git a/sms_contact/index.php b/sms_contact/index.php new file mode 100644 index 0000000..00c678b --- /dev/null +++ b/sms_contact/index.php @@ -0,0 +1,86 @@ + + + + + send me a (short) message + + + + + +
+Error: [' . $exception->getCode() . '] ' . $exception->getMessage() . '

'; +}); + +require_once 'xmlrpc/lib/xmlrpc.inc'; +require_once 'sipgateAPI.php'; +require_once 'blacklist.php'; +require_once 'config.php'; + +$sipgate = new sipgateAPI($username, $password); +$balance = $sipgate->getBalance(); + +//echo '

Guthaben: ' . round($balance['CurrentBalance']['TotalIncludingVat'], 2) . ' ' . $balance['CurrentBalance']['Currency'] . '

'; + +if ($_POST) { + $message = str_replace("\r", "", trim($_POST['message'])); + $blacklist = read_blacklist($blocked); + + if (!isset($_POST['message'])) { + throw new Exception('No message!', 5); + } + if ($_POST['antispam'] != md5($message)) { + throw new Exception('Are you cheating me?! Please activate Javascript!', 1); + } + if (strlen($message) > 160) { + throw new Exception('Your message is too long!'); + } + if ($balance['CurrentBalance']['TotalIncludingVat'] < 1) { + throw new Exception('No balance left!', 2); + } + if ($time = is_blacklisted($blacklist, $_SERVER['REMOTE_ADDR'])) { + throw new Exception('You can only send one SMS per day! Please wait ' . format_duration($blocked - (time() - $time)) . '!', 3); + } + + //$sipgate->sendSMS($mobilenumber, $message, NULL, $mobilenumber); + if ($_SERVER['REMOTE_ADDR'] != '172.0.0.1') $blacklist[] = array($_SERVER['REMOTE_ADDR'], time()); + + echo '

SMS has been send!

+

Thank you :)

+

back

'; + write_blacklist($blacklist); +} +else { + $message = (isset($_REQUEST['message'])) ? $_REQUEST['message'] : ''; + + echo '
+ + + + +
To++' . $mobilenumber . '
Message
Length' . strlen($message) . ' (left: ' . (160 - strlen($message)) . ')
+ + +
'; +} + +function format_duration($time) { + if ($time < 60) { + return $time . ' seconds'; + } + elseif ($time < 3600) { + return floor($time/60) . ' minutes'; + } + else { + return floor($time/3600) . ':' . floor(($time%3600)/60) . ' hours'; + } +} + +?> +
+ + diff --git a/sms_contact/js/md5.js b/sms_contact/js/md5.js new file mode 100644 index 0000000..3b1ad67 --- /dev/null +++ b/sms_contact/js/md5.js @@ -0,0 +1,9 @@ +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ +var hexcase=0;function hex_md5(a){return rstr2hex(rstr_md5(str2rstr_utf8(a)))}function hex_hmac_md5(a,b){return rstr2hex(rstr_hmac_md5(str2rstr_utf8(a),str2rstr_utf8(b)))}function md5_vm_test(){return hex_md5("abc").toLowerCase()=="900150983cd24fb0d6963f7d28e17f72"}function rstr_md5(a){return binl2rstr(binl_md5(rstr2binl(a),a.length*8))}function rstr_hmac_md5(c,f){var e=rstr2binl(c);if(e.length>16){e=binl_md5(e,c.length*8)}var a=Array(16),d=Array(16);for(var b=0;b<16;b++){a[b]=e[b]^909522486;d[b]=e[b]^1549556828}var g=binl_md5(a.concat(rstr2binl(f)),512+f.length*8);return binl2rstr(binl_md5(d.concat(g),512+128))}function rstr2hex(c){try{hexcase}catch(g){hexcase=0}var f=hexcase?"0123456789ABCDEF":"0123456789abcdef";var b="";var a;for(var d=0;d>>4)&15)+f.charAt(a&15)}return b}function str2rstr_utf8(c){var b="";var d=-1;var a,e;while(++d>>6)&31),128|(a&63))}else{if(a<=65535){b+=String.fromCharCode(224|((a>>>12)&15),128|((a>>>6)&63),128|(a&63))}else{if(a<=2097151){b+=String.fromCharCode(240|((a>>>18)&7),128|((a>>>12)&63),128|((a>>>6)&63),128|(a&63))}}}}}return b}function rstr2binl(b){var a=Array(b.length>>2);for(var c=0;c>5]|=(b.charCodeAt(c/8)&255)<<(c%32)}return a}function binl2rstr(b){var a="";for(var c=0;c>5]>>>(c%32))&255)}return a}function binl_md5(p,k){p[k>>5]|=128<<((k)%32);p[(((k+64)>>>9)<<4)+14]=k;var o=1732584193;var n=-271733879;var m=-1732584194;var l=271733878;for(var g=0;g>16)+(d>>16)+(c>>16);return(b<<16)|(c&65535)}function bit_rol(a,b){return(a<>>(32-b))}; diff --git a/sms_contact/js/sms.js b/sms_contact/js/sms.js new file mode 100644 index 0000000..3f2de00 --- /dev/null +++ b/sms_contact/js/sms.js @@ -0,0 +1,33 @@ +String.prototype.ltrim = function (clist) { + if (clist) return this.replace(new RegExp ('^[' + clist + ']+'), ''); + return this.replace(/^\s+/, ''); +} + +String.prototype.rtrim = function (clist) { + if (clist) return this.replace(new RegExp ('[' + clist + ']+$'), ''); + return this.replace(/\s+$/, ''); +} + +String.prototype.trim = function (clist) { + if (clist) return this.ltrim(clist).rtrim(clist); + return this.ltrim().rtrim(); +}; + +function update_length(msg) { + document.getElementById('length').innerHTML = msg.value.trim().length; + document.getElementById('left').innerHTML = 160 - msg.value.trim().length; + document.getElementById('left').style.color = (msg.value.trim().length > 160) ? 'red' : 'green'; +} + +function send(frm) { + frm.message.value = frm.message.value.trim() + frm.antispam.value = hex_md5(frm.message.value); + + if (frm.message.value.length > 160) { + alert('Message is too long!'); + return false; + } + else { + return true; + } +} diff --git a/sms_contact/sipgateAPI.php b/sms_contact/sipgateAPI.php new file mode 100644 index 0000000..29a4f63 --- /dev/null +++ b/sms_contact/sipgateAPI.php @@ -0,0 +1,267 @@ + + * Requires "XML-RPC for PHP" (http://phpxmlrpc.sourceforge.net) + * + * This is a private project. + * It uses the API provided by sipgate, but sipgate can not and will not support any problems with this software. + * You can find the API (including documentation) here: http://www.sipgate.de/api + * + * @package sipgateAPI + * + * @version 0.1 + * @author Christian Schmidt + */ +class sipgateAPI +{ + const ClientVersion = 0.1; + const ClientName = 'sipgateAPI with PHP'; + const ClientVendor = 'Christian Schmidt'; + + const SIP_URI_prefix = 'sip:'; + const SIP_URI_host = '@sipgate.de'; + + private $client = null; + private $url; + private $debug; + + + /** + * Checks if XML-RPC for PHP is included + * + * @throws sipgateAPI_Exception when XML-RPC for PHP is not available + */ + public function __construct($username, $password, $debug = FALSE) + { + // Check if xmlrpc is included + if (!class_exists("xmlrpc_client")) { + throw new sipgateAPI_Exception ('You need "xmlrpc for PHP" - Please download at http://phpxmlrpc.sourceforge.net'); + }; + + $this->debug = $debug; + + if ( !empty($username) AND !empty($password) ) { + $this->getClient($username, $password); + } + else { + throw new sipgateAPI_Exception('Provide valid credentials'); + }; + + return $this->client; + } + + + + /** + * configures a client to connect to XML-RPC server + * + * @param string $username Your sipgate username - the one you use on the website, NOT your SIP-ID + * @param string $password + * + * @return object xmlrpc-client + */ + private function getClient($username, $password) + { + if (null === $this->client) { + + // Build URL + $this->url = "https://" . urlencode($username) . ":" . urlencode($password); + if (self::isTeam($username)) { + $this->url .= "@api.sipgate.net:443/RPC2"; + + } else { + $this->url .= "@samurai.sipgate.net:443/RPC2"; + } + + // create client + $this->client = new xmlrpc_client($this->url); + + if ($this->debug) { + $this->client->setDebug(2); + } + + $this->client->setSSLVerifyPeer(FALSE); + } + + return $this->client; + + } // function setClient + + + private function isTeam($username) + { + return !FALSE == strpos($username, '@'); + } + + /** + * implements samurai.BalanceGet + * + * @param void + * + * @return array + * + * @throws sipgateAPI_Server_Exception on Server responses != 200 OK + * + */ + public function getBalance() + { + // // checks if method is supported + // if ( ! $this->methodSupported(__FUNCTION__) ) { + // throw new sipgateAPI_Exception("Method not supported", 400); + // } + + // create message + $m = new xmlrpcmsg('samurai.BalanceGet'); + + // send message + $r = $this->client->send($m); + + if (!$r->faultCode()) { + $php_r = php_xmlrpc_decode($r->value()); + unset($php_r["StatusCode"]); + unset($php_r["StatusString"]); + return $php_r; + } + else { + throw new sipgateAPI_Server_Exception($r->faultString(), $r->faultCode()); + } + } + + + /** + * sending SMS + * + * Sending a text message to a (mobile) phone. Message will be cut off after 160 characters + * + * @param string $to mobile number, example: 491701234567 + * @param string $message cut off after 160 chars + * @param string $time unix timestamp in UTC + * + * @return + */ + public function sendSMS($to, $message, $time = NULL, $from = NULL) + { + $remote = self::SIP_URI_prefix . $to . self::SIP_URI_host; + $local = (isset($from)) ? (self::SIP_URI_prefix . $from . self::SIP_URI_host) : NULL; + + $message = substr($message, 0, 160); + + $this->samurai_SessionInitiate($local, $remote, "text", $message, $time); + } + + + + + + /** + * sending a PDF file as fax + * + * @param string $to fax number, example: 492111234567 + * @param string $file + * @param string $time unix timestamp in UTC + * + * @return string Returns SessionID + */ + public function sendFAX($faxnumber, $file, $time = NULL) + { + $number = self::SIP_URI_prefix . $faxnumber . self::SIP_URI_host; + + $file = realpath($file); + + if ( !file_exists($file) ) { + throw new Exception("PDF file does not exist"); + } + elseif ( strtolower(pathinfo($file, PATHINFO_EXTENSION)) != 'pdf' ) { + throw new Exception("No PDF file"); + }; + + + $pdf_base64 = base64_encode(file_get_contents($file)); + $r = $this->samurai_SessionInitiate(NULL, $number, "fax", $pdf_base64, $time); + + return $r; + } + + /** + * implements samurai.SessionInitiate + * + *@param string $LocalUri as SIP-URI + *@param string $RemoteUri as SIP-URI + *@param string $TOS Type of service as defined in $availableTOS + *@param string $Content depends on TOS + *@param dateTime $schedule as unix timestamp + * + * @return string SessionID, if available + * + * @throws sipgateAPI_Server_Exception on Server responses != 200 OK + */ + protected function samurai_SessionInitiate($LocalUri, $RemoteUri, $TOS, $Content, $Schedule = NULL) + { + if ( isset($LocalUri) ) { + $val_a["LocalUri"] = new xmlrpcval($LocalUri); + }; + + if ( isset($RemoteUri) ) { + $val_a["RemoteUri"] = new xmlrpcval($RemoteUri); + } + else { + throw new sipgateAPI_Exception("No RemoteUri"); + }; + + if ( isset($TOS) ) { + $val_a["TOS"] = new xmlrpcval($TOS); + } + else { + throw new sipgateAPI_Exception("No valid TOS"); + }; + + if ( isset($Content) ) { + $val_a["Content"] = new xmlrpcval($Content); + }; + + if ( isset($Schedule) ) { + $val_a["Schedule"] = new xmlrpcval(iso8601_encode($Schedule), "dateTime.iso8601"); + }; + + $val_s = new xmlrpcval(); + $val_s->addStruct($val_a); + $v = array(); + $v[] = $val_s; + + // create message + $m = new xmlrpcmsg('samurai.SessionInitiate', $v); + + // send message + $r = $this->client->send($m); + + + if (!$r->faultCode()) { + $php_r = php_xmlrpc_decode($r->value()); + return $php_r["SessionID"]; + } + else { + throw new sipgateAPI_Server_Exception($r->faultString(), $r->faultCode()); + } + } +} diff --git a/sms_contact/sipgateAPI_Exception.php b/sms_contact/sipgateAPI_Exception.php new file mode 100644 index 0000000..4e2f5a6 --- /dev/null +++ b/sms_contact/sipgateAPI_Exception.php @@ -0,0 +1,31 @@ +