added sms contact form for my webblog

This commit is contained in:
Steffen Vogel 2011-02-07 20:20:22 +01:00
parent 540d6cd83f
commit c5ddee94aa
8 changed files with 460 additions and 0 deletions

1
sms_contact/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
config.php

View file

@ -0,0 +1 @@
127.0.0.1 1297105523
1 127.0.0.1 1297105523

32
sms_contact/blacklist.php Normal file
View file

@ -0,0 +1,32 @@
<?php
function read_blacklist($time = 86400) {
$blacklisted = array();
$handle = fopen('blacklist.csv', 'r');
while (($data = fgetcsv($handle, 100, "\t")) !== FALSE ) {
if (count($data) == 2 && time() - $data[1] < $time) {
$blacklisted[] = $data;
}
}
fclose ($handle);
return $blacklisted;
}
function is_blacklisted($blacklist, $ip) {
foreach ($blacklist as $entry) {
if ($entry[0] == $ip)
return $entry[1];
}
return FALSE;
}
function write_blacklist($blacklist) {
$handle = fopen('blacklist.csv', 'w');
foreach($blacklist as $entry) {
fputcsv($handle, $entry, "\t");
}
fclose ($handle);
}
?>

86
sms_contact/index.php Normal file
View file

@ -0,0 +1,86 @@
<?= '<?xml version="1.0" encoding="UTF-8"' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de-DE" lang="de-DE">
<head>
<title>send me a (short) message</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="js/md5.js" type="text/javascript"></script>
<script src="js/sms.js" type="text/javascript"></script>
</head>
<body>
<div id="sms_contact">
<?php
set_exception_handler(function($exception) {
echo '<p style="color: red; font-weight: bold;">Error: [' . $exception->getCode() . '] ' . $exception->getMessage() . '</p>';
});
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 '<p>Guthaben: ' . round($balance['CurrentBalance']['TotalIncludingVat'], 2) . ' ' . $balance['CurrentBalance']['Currency'] . '</p>';
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 '<h3>SMS has been send!</h3>
<p>Thank you :)</p>
<p><a href="javascript:history.go(-1)" title="back">back</a></p>';
write_blacklist($blacklist);
}
else {
$message = (isset($_REQUEST['message'])) ? $_REQUEST['message'] : '';
echo '<form name="sms" onsubmit="send(this);" action="' . $_SERVER['PHP_SELF'] . '" method="post">
<table>
<tr><td>To</td><td>++' . $mobilenumber . '</td></tr>
<tr><td>Message</td><td><textarea onfocus="update_length(this);" onkeyup="update_length(this);" name="message" cols="40" rows="5">' . $message . '</textarea></td></tr>
<tr><td>Length</td><td><span id="length">' . strlen($message) . '</span> (left: <span id="left" style="color: green;">' . (160 - strlen($message)) . '</span>)</td></tr>
</table>
<input type="hidden" name="antispam" />
<input type="submit" value="send" />
</form>';
}
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';
}
}
?>
</div>
</body>
</html>

9
sms_contact/js/md5.js Normal file
View file

@ -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<c.length;d++){a=c.charCodeAt(d);b+=f.charAt((a>>>4)&15)+f.charAt(a&15)}return b}function str2rstr_utf8(c){var b="";var d=-1;var a,e;while(++d<c.length){a=c.charCodeAt(d);e=d+1<c.length?c.charCodeAt(d+1):0;if(55296<=a&&a<=56319&&56320<=e&&e<=57343){a=65536+((a&1023)<<10)+(e&1023);d++}if(a<=127){b+=String.fromCharCode(a)}else{if(a<=2047){b+=String.fromCharCode(192|((a>>>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<a.length;c++){a[c]=0}for(var c=0;c<b.length*8;c+=8){a[c>>5]|=(b.charCodeAt(c/8)&255)<<(c%32)}return a}function binl2rstr(b){var a="";for(var c=0;c<b.length*32;c+=8){a+=String.fromCharCode((b[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<p.length;g+=16){var j=o;var h=n;var f=m;var e=l;o=md5_ff(o,n,m,l,p[g+0],7,-680876936);l=md5_ff(l,o,n,m,p[g+1],12,-389564586);m=md5_ff(m,l,o,n,p[g+2],17,606105819);n=md5_ff(n,m,l,o,p[g+3],22,-1044525330);o=md5_ff(o,n,m,l,p[g+4],7,-176418897);l=md5_ff(l,o,n,m,p[g+5],12,1200080426);m=md5_ff(m,l,o,n,p[g+6],17,-1473231341);n=md5_ff(n,m,l,o,p[g+7],22,-45705983);o=md5_ff(o,n,m,l,p[g+8],7,1770035416);l=md5_ff(l,o,n,m,p[g+9],12,-1958414417);m=md5_ff(m,l,o,n,p[g+10],17,-42063);n=md5_ff(n,m,l,o,p[g+11],22,-1990404162);o=md5_ff(o,n,m,l,p[g+12],7,1804603682);l=md5_ff(l,o,n,m,p[g+13],12,-40341101);m=md5_ff(m,l,o,n,p[g+14],17,-1502002290);n=md5_ff(n,m,l,o,p[g+15],22,1236535329);o=md5_gg(o,n,m,l,p[g+1],5,-165796510);l=md5_gg(l,o,n,m,p[g+6],9,-1069501632);m=md5_gg(m,l,o,n,p[g+11],14,643717713);n=md5_gg(n,m,l,o,p[g+0],20,-373897302);o=md5_gg(o,n,m,l,p[g+5],5,-701558691);l=md5_gg(l,o,n,m,p[g+10],9,38016083);m=md5_gg(m,l,o,n,p[g+15],14,-660478335);n=md5_gg(n,m,l,o,p[g+4],20,-405537848);o=md5_gg(o,n,m,l,p[g+9],5,568446438);l=md5_gg(l,o,n,m,p[g+14],9,-1019803690);m=md5_gg(m,l,o,n,p[g+3],14,-187363961);n=md5_gg(n,m,l,o,p[g+8],20,1163531501);o=md5_gg(o,n,m,l,p[g+13],5,-1444681467);l=md5_gg(l,o,n,m,p[g+2],9,-51403784);m=md5_gg(m,l,o,n,p[g+7],14,1735328473);n=md5_gg(n,m,l,o,p[g+12],20,-1926607734);o=md5_hh(o,n,m,l,p[g+5],4,-378558);l=md5_hh(l,o,n,m,p[g+8],11,-2022574463);m=md5_hh(m,l,o,n,p[g+11],16,1839030562);n=md5_hh(n,m,l,o,p[g+14],23,-35309556);o=md5_hh(o,n,m,l,p[g+1],4,-1530992060);l=md5_hh(l,o,n,m,p[g+4],11,1272893353);m=md5_hh(m,l,o,n,p[g+7],16,-155497632);n=md5_hh(n,m,l,o,p[g+10],23,-1094730640);o=md5_hh(o,n,m,l,p[g+13],4,681279174);l=md5_hh(l,o,n,m,p[g+0],11,-358537222);m=md5_hh(m,l,o,n,p[g+3],16,-722521979);n=md5_hh(n,m,l,o,p[g+6],23,76029189);o=md5_hh(o,n,m,l,p[g+9],4,-640364487);l=md5_hh(l,o,n,m,p[g+12],11,-421815835);m=md5_hh(m,l,o,n,p[g+15],16,530742520);n=md5_hh(n,m,l,o,p[g+2],23,-995338651);o=md5_ii(o,n,m,l,p[g+0],6,-198630844);l=md5_ii(l,o,n,m,p[g+7],10,1126891415);m=md5_ii(m,l,o,n,p[g+14],15,-1416354905);n=md5_ii(n,m,l,o,p[g+5],21,-57434055);o=md5_ii(o,n,m,l,p[g+12],6,1700485571);l=md5_ii(l,o,n,m,p[g+3],10,-1894986606);m=md5_ii(m,l,o,n,p[g+10],15,-1051523);n=md5_ii(n,m,l,o,p[g+1],21,-2054922799);o=md5_ii(o,n,m,l,p[g+8],6,1873313359);l=md5_ii(l,o,n,m,p[g+15],10,-30611744);m=md5_ii(m,l,o,n,p[g+6],15,-1560198380);n=md5_ii(n,m,l,o,p[g+13],21,1309151649);o=md5_ii(o,n,m,l,p[g+4],6,-145523070);l=md5_ii(l,o,n,m,p[g+11],10,-1120210379);m=md5_ii(m,l,o,n,p[g+2],15,718787259);n=md5_ii(n,m,l,o,p[g+9],21,-343485551);o=safe_add(o,j);n=safe_add(n,h);m=safe_add(m,f);l=safe_add(l,e)}return Array(o,n,m,l)}function md5_cmn(h,e,d,c,g,f){return safe_add(bit_rol(safe_add(safe_add(e,h),safe_add(c,f)),g),d)}function md5_ff(g,f,k,j,e,i,h){return md5_cmn((f&k)|((~f)&j),g,f,e,i,h)}function md5_gg(g,f,k,j,e,i,h){return md5_cmn((f&j)|(k&(~j)),g,f,e,i,h)}function md5_hh(g,f,k,j,e,i,h){return md5_cmn(f^k^j,g,f,e,i,h)}function md5_ii(g,f,k,j,e,i,h){return md5_cmn(k^(f|(~j)),g,f,e,i,h)}function safe_add(a,d){var c=(a&65535)+(d&65535);var b=(a>>16)+(d>>16)+(c>>16);return(b<<16)|(c&65535)}function bit_rol(a,b){return(a<<b)|(a>>>(32-b))};

33
sms_contact/js/sms.js Normal file
View file

@ -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;
}
}

267
sms_contact/sipgateAPI.php Normal file
View file

@ -0,0 +1,267 @@
<?php
/**
* A PHP wrapper for sipgateAPI aka SAMURAI
*
* 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
*
*
* @author Christian Schmidt
* @license
* @copyright Copyright 2007, Christian Schmidt
*
* @package sipgateAPI
*/
/**
* Include Exception handling
*/
require_once 'sipgateAPI_Exception.php';
/**
* Implements the samurai functionality for PHP programers. So you don't have to mess around with XML-RPC<br />
* 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 <i>samurai.BalanceGet</i>
*
* @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 <i>samurai.SessionInitiate</i>
*
*@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());
}
}
}

View file

@ -0,0 +1,31 @@
<?php
/**
*
* @author Christian Schmidt
* @license
* @copyright Copyright &copy; 2007, Christian Schmidt
*
* @package sipgateAPI
* @subpackage sipgateAPI_Exception
*/
/**
* Extends PHP5 Exception handling
*
* @package sipgateAPI
* @subpackage sipgateAPI_Exception
*/
class sipgateAPI_Exception extends Exception
{
}
/**
* Throws Exeptions on server responses != "200 OK"
* @package sipgateAPI
* @subpackage sipgateAPI_Exception
*/
class sipgateAPI_Server_Exception extends sipgateAPI_Exception
{
}