Feb 26, 2011

Quran Translation needs Your Help.

I understand that the text here might seem a little long and boring, but please bear with me. This is important. If you must skim, please read the last few paragraphs.

About an year ago, I grew frustrated with the lack of a readily usable version of the Quran translation in Dhivehi. Back then, I wanted to be able to use the Dhivehi translation with Zekr; a free (as in freedom) versatile open source Quranic study tool that came standard with a multitude of translations, recitations, localizations and so forth. I wished that the Dhivehi translation was also included among these for everyone to benefit from. For this, I needed a standards compliant plaintext UNICODE version of the translation which, needless to say was not available.

I searched high and low to find such a text. The PDF's available on Presidency Maldives where just that. PDF's from which - despited many hours spent trying - nothing "useful" could be extracted. All the while, interest in the efforts grew, and a few of my friends (Bunyameen, his brothers, Nisham, Nadheem and so on to name a few) volunteered to help.

We approached the Islamic Ministry, the Presidents Office, and all our friends in nooks and crannies of the government trying to obtain in the very least, an MS Word document that we could work with. None of these people were willing to part with anything useful - officially stating the reason that the subject of the Quran Translation was too "volatile" for them to release it. That there were people looking for commercial/political/religious/social/etc gain from the text.


Feb 5, 2011

Dhiraagu webSMS Conduit

I posted a simple bash script a long time ago to try and ease the process of sending webSMS's. While the age when everybody around here was messing around with the service is long gone, I have personally found the service to be quite useful (it's free after all!), and still occasionally mess around with it. The script works through and through and has served it's purpose well over the ages. The problem however, was that it still required the exchange of a (relatively) large amount of data between the client (me) and the server(Dhiraagu). While this is inconsequential on a regular broadband connection, it is a problem on my rather expensive mobile data connection.

Thus, out of this particular need, and after a brief spurt of late night coding (4:00 am - 4:15am?) the following PHP script was born. It is to live on my hosted server, and there act as a "Conduit" between myself and Dhiraagu. As you can see, it is, more or less, a "port" of the original Bash script to PHP...and I hope the PHP gods won't rain thunder and rocks on my head for the horrible job I did of it.

I do wish however that the people at Dhiraagu would update this site, and maybe provide a simple API or something to developers. They also need to reconsider the security..for instance an unexpected upshot of all this, is that THIS script allows me to use SSL between myself and my conduit. Dhiraagu itself doesn't provide this functionality. Not that I think it's of particular relevance, but SSL is always a good thing.

FUN FACT: No matter how long your webSMS password is, only the first 8 characters matter (I'll admit 8 isn't so bad..)

Anyways...here be the thing.

Enjoy.

<?php
/*....
PHP script to act as a go-between for Dhiraagu websms
to minimize data-exchange. Ideally for use over a
mobile network.
 
 
just upload the php file to some place that supports
php_curl and make a standard GET request to the file
with the follwing parameters:
 
user,pass,num,msg,cookie
 
where cookie is optional, and is the session string of
an existing session.
 
The Script returns a JSON encoded status message.
*/
 
$old_error_handler = set_error_handler("myErrorHandler");
$SessionData=array(
'status' => 'OK',
'count' => NULL,
'cookie' => NULL,
'retries' => 0,
);
 
function terminate_now() {
    global $SessionData;
    echo json_encode($SessionData)."\n";
    exit(1);
}
 
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
     
    global $SessionData;
    if (!(error_reporting() & $errno)) {
        return;
    }
     
    switch ($errno) {
        case E_USER_ERROR:
        $SessionData['status']="ERR: ".$errstr;
        terminate_now();
        break;
         
        case E_USER_WARNING:
        $SessionData['status']="WARN: ".$errstr;
        break;
         
        default:
        $SessionData['status']="ERRUNKWN: ".$errstr;
        terminate_now();
        break;
    }
     
    return true;
}
 
 
function make_curl_request($url,$post_params,$useCookie) {
     
    global $SessionData;
     
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch,CURLOPT_AUTOREFERER,1);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
    curl_setopt($ch,CURLOPT_HEADER,1);
    curl_setopt($ch, CURLOPT_POST, 2);
    curl_setopt($ch, CURLOPT_POSTFIELDS,$post_params);
    curl_setopt($ch,CURLOPT_COOKIESESSION,1);
    if($useCookie) {
        curl_setopt($ch,CURLOPT_COOKIE,'Dhi='.$SessionData['cookie']);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     
    $output = curl_exec($ch);
    curl_close($ch);
     
    return $output;
     
     
}
 
function login()
{
    global $SessionData;
    $username=$_GET['user'];
    $password=$_GET['pass'];
     
    $return=make_curl_request('http://websms.dhimobile.com.mv/cgi-bin/websms/index.pl',
    'username='.urlencode($username).'&password='.urlencode($password),FALSE);
     
    if(preg_match('/^Set-Cookie: Dhi=(.*?);/m', $return, $cookie_out)) {
        $SessionData['cookie']=$cookie_out[1];
         
        //CHECK DAILY QUOTA
        if(preg_match('/send (.*?) more/',$return,$msg_count)) {
            if(($SessionData['count']=$msg_count[1])<1){
                trigger_error('You have Reached your Daily Quota',E_USER_ERROR);
                 
                } else {
                sendsms();
            }
        }
        return true;
         
        } else {
        trigger_error('Invalid Username andor Password',E_USER_ERROR);
        return false;
    }
}
 
function sendsms() {
     
    global $SessionData;
    $number=$_GET['num'];
    $message=$_GET['msg'];
     
    if(strlen($message) > 140) {
        trigger_error('Message Truncated',E_USER_WARNING);
        $message=substr($message,0,140);
    }
     
    $return=make_curl_request('http://websms.dhimobile.com.mv/cgi-bin/websms/send_message.pl',
    'mobilenumber='.urlencode($number).'&message='.urlencode($message),TRUE);
     
    //VALIDATE THE RETURN STUFF
    if(preg_match('/send (.*?) more/',$return,$msg_count)) {
        $SessionData['count']=$msg_count[1];
        } else {
        if(($SessionData['retries']++)>3){
            trigger_error('maximum number of retries exceeded',E_USER_ERROR);
        }
        login();
    }
     
}
 
 
if (isset($_GET['user']) && isset($_GET['pass']) && isset($_GET['msg']) && isset($_GET['num'])) {
if(preg_match("/^7[4-9][0-9]{5}$/",$_GET['num'],$number)){
        $_GET['num']=$number[0];
        } else {
        trigger_error('Invalid Number Format',E_USER_ERROR);
    }
    } else {
    trigger_error('Insufficiant Arguments',E_USER_ERROR);
}
 
if(isset($_GET['cookie'])){
    $SessionData['cookie']=$_GET['cookie'];
    sendsms();
    } else {
    login();
}
 
 
terminate_now();
?>


and then we have this modified version of the bash script to help make calls to the conduit

#!/usr/bin/env bash

#..........................................
# Bash helper script for Dhiraagu webSMS
# using the webSMS Conduit script from
# http://www.kudanai.com
#
#
# 2010 - kudanai

user= #defaultuser
pass= #defaultpass
dirlist=~/.wsmsdir
serverURL="http://192.168.1.2:8080/websms.php"
purge=0

function printhelp {
cat << EOT
Dhiraague WebSMS Conduit helper- KudaNai (kudanai.blogspot.com)
USAGE: $0 [OPTIONS...] -n number 'message'

OPTIONS
 -h  Print this help and exit
 -N  New Session. Do not reuse old cookies.
 -d  Override default directory file. The Directory file
     is a comma seperated file containing name,number pairs
 -u  USERNAME Override default username.
 -p  PASSWORD Override default password.

  Please note that the -n argument is MANDATORY

EOT
exit
}

function sendsms {
 
 if [ -e ${dirlist} ];then dcheck=`cat ${dirlist} | grep -w ${number} | cut -f2 -d","`;fi 
 if [ -n "${dcheck}" ];then number=${dcheck};fi

 if [ $purge -lt 1 ]
 then
  if [ -e /tmp/$user.wsmscookie ]
  then
   cookie=$(cat /tmp/$user.wsmscookie)
  fi
 fi
 return=$(curl --silent -G \
  -d "user=${user}" \
  -d "pass=${pass}" \
  -d "num=${number}" \
  --data-urlencode "msg=${message}" \
  -d "cookie=${cookie}" \
  $serverURL
 )
 echo $return

 if [[ "${return}" =~ \"cookie\":\"(.*)?\", ]]
 then
  echo ${BASH_REMATCH[1]} > /tmp/$user.wsmscookie
 fi
}

while getopts 'hNn:u:p:d:' Option
do
 case $Option in
  u) user="${OPTARG}" ;;
  p) pass="${OPTARG}" ;;
  N) purge=1;;
  d) dirlist="${OPTARG}" ;;
  n) number="${OPTARG}" ;;
  h) printhelp ;;
  ?) printhelp ;;
 esac
done

shift $(( $OPTIND - 1 ))
message=$1
sendsms