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
+
+
+
+
+
+
+
+
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 @@
+