Difference between revisions of "WHMcs SecondLife plugin"

From Second Life Wiki
Jump to navigation Jump to search
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{LSL Header}}
{{LSL Header}}
==WHMcs SL gateway plugin==
{{db-g7}}
Befor you rush to glance at the code, please read this.
 
I made this plugin some time ago while I was still learning the ins and outs of external communication and thise plugin was created with snippets I had in multiple projects so it is anything but efficient :)
 
I am releasing it to give others an heads start or give an idea about how to do it, this was written on the old LSL engine and could get an extra overhaul to reduce it to a signle script using MONO.
 
Use of this plugin is at own risk, create a beta site to test/play with it befor being 200% sure to use it, it was created with testing of a certain version but as it directly modifies the database it *should* work with all).
 
 
The terminal uses 3 scripts:
 
Terminal - this is the interactive script wiith the user
 
Component A - the http handler
 
Component B - this script IM`s the user and to avoid the delay timer of 2 seconds on the main script
 
Database changes
 
You will have to alter the user table and add 2 colums "sl_name" and "sl_key"
 
 
Terminal
<lsl>
integer LINK_TERM  = 13958260;
integer LINK_COMM  = 13958261;
integer LINK_DELAY  = 13958262;
 
string split;
string split2;
string cmd;
string cmd2;
string kl_list(integer i)
{
    list split = llParseString2List(split, ["|"],[]);
    cmd = llList2String(split, i);
    return cmd;
}
string kl_listen(integer i)
{
    list split2 = llParseString2List(split2, [" "],[]);
    cmd2 = llList2String(split2, i);
    return cmd2;
}
 
list klParseButtons( integer vIntPage )
{
    list vLstReturn;
    integer vIntLength = llGetListLength( klButtons );
    integer vIntStart = llAbs(vIntPage) * 11;
 
    if (vIntLength - vIntStart > 0)
    {
        if (vIntLength - vIntStart > 12)
        {
            vLstReturn += llList2List( klButtons, vIntStart + 9, vIntStart + 10 );
            if (vIntPage < 10)
            {
                vLstReturn += ["MORE (0" + (string)(vIntPage + 1) + ")"];
            } else {
                vLstReturn += ["MORE (" + (string)(vIntPage + 1) + ")"];
            }
   
            vLstReturn += llList2List( klButtons, vIntStart + 6, vIntStart + 8 );
            vLstReturn += llList2List( klButtons, vIntStart + 3, vIntStart + 5 );
            vLstReturn += llList2List( klButtons, vIntStart, vIntStart + 2 );
        } else {
            integer i = vIntLength - 1;
            for (i; i - 2 >= vIntStart; i -= 3)
            {
                vLstReturn += llList2List( klButtons, i -2, i );
            }
            if (i >= vIntStart)
            {
                vLstReturn += llList2List( klButtons, vIntStart, i );
            }
        }
    }
    return vLstReturn;
}
 
//////////////// END Functions \\\\\\\\\\\\\\\\
 
key creator = "66879809-f806-469b-998e-bc582728cabf";
key usrNow = "";
integer dChannel;
integer DEBUG_mem = FALSE;
 
integer ONLINE = FALSE;
integer UPDATE = FALSE;
string kl_state;
list klButtons;
 
string dialog_text = "My company text here \n\n";
float exchange = 266;
 
string userid;
list invoice_id = [];
list invoice_name = [];
list invoice_amount = [];
list invoice_linden = [];
 
string invoice_pay_id = "";
string invoice_pay_name = "";
string invoice_pay_amount = "";
string invoice_pay_linden = "";
 
 
//////////////// END Variables \\\\\\\\\\\\\\\\
 
string dialog(string a)
{
    if (a == "Invoice")
    {
        kl_state = "invoice";
        klButtons = invoice_name;
        klButtons = (klButtons = []) + klButtons + ["Exit"];
    } 
   
    llDialog(usrNow , dialog_text, klParseButtons(0), dChannel);
 
    a = "";
    return a;
}
 
//////////////// END Dialogs \\\\\\\\\\\\\\\\
 
default
{
    on_rez(integer startparam)
    {
        llResetScript();
    }
 
    state_entry()
    {
        llSetPayPrice(PAY_DEFAULT, [PAY_DEFAULT, PAY_DEFAULT, PAY_DEFAULT, PAY_DEFAULT]);
        dChannel = (integer)llFrand(99.0);
        if (dChannel == 0)
        {
            dChannel = (integer)llFrand(99.0);
        }
        llListen(dChannel,"","","");
    }
 
    touch_start(integer agent)
    {
        usrNow = llDetectedKey(0);
        llMessageLinked(LINK_THIS, LINK_DELAY, "Please wait...", usrNow);
        llResetOtherScript("KeyLess component A");
        llSleep(0.1);
       
        state normal;
    }
}
 
state normal
{
    state_entry()
    {
        llListen(dChannel,"","","");
        llMessageLinked(LINK_THIS, LINK_COMM, "user:check", usrNow);
    }
 
    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == LINK_TERM)
        {           
            split = str;
            if (kl_list(0) == "error")
            {
                llMessageLinked(LINK_THIS, LINK_DELAY, kl_list(1), usrNow);
            }
           
            if (kl_list(0) == "reset")
            {
                llResetScript();
            }
           
            if (kl_list(0) == "user:unregisterd")
            {
                llSetTimerEvent(60);
                llMessageLinked(LINK_THIS, LINK_DELAY, "Please verify your account within 60 seconds, replace < > with your info:", usrNow);
                llMessageLinked(LINK_THIS, LINK_DELAY, "/"+ (string)dChannel +" verify <first name> <lastname> <email>", usrNow);
            }
           
            if (kl_list(0) == "user:registerd")
            {
                userid = kl_list(1);
                llMessageLinked(LINK_THIS, LINK_DELAY, "Checking for open invoices...", usrNow);
                llMessageLinked(LINK_THIS, LINK_COMM, "invoice:check|"+ userid, usrNow);
            }
           
            if (kl_list(0) == "user:verified")
            {
                userid = kl_list(1);
                llMessageLinked(LINK_THIS, LINK_DELAY, "Thank you for verifying, checking for open invoices...", usrNow);
                llMessageLinked(LINK_THIS, LINK_COMM, "invoice:check|"+ userid, usrNow);
            }
           
            if (kl_list(0) == "invoice" && kl_list(1) == "list")
            {
                integer q = 2;
                while (kl_list(q) != "" && kl_list(q + 1) != "" && kl_list(q + 2) != "")
                { 
                    invoice_id = (invoice_id = []) + invoice_id + [kl_list(q)];
                    invoice_name = (invoice_name = []) + invoice_name + [kl_list(q + 1)];
                    invoice_amount = (invoice_amount = []) + invoice_amount + [kl_list(q + 2)];
                   
                    integer linden = llCeil(( (float)kl_list(q + 2) * exchange) + (( (float)kl_list(q + 2) * exchange) / 100 * 3.5));
                   
                    invoice_linden = (invoice_linden = []) + invoice_linden + [(string)linden];
                   
                    dialog_text += kl_list(q + 1) +": $"+ kl_list(q + 2) + " (L$ "+ (string)linden +") \n";
                    q = q + 3;
                }
                llSetTimerEvent(60);
                dialog("Invoice");
            }
           
            if (kl_list(1) == "payed")
            {
                llMessageLinked(LINK_THIS, LINK_DELAY, "Invoice: "+ kl_list(2) +" has been payed, thank you.", usrNow);
                llResetScript();
            }
        }
    }
   
    listen(integer dChannel, string vStrName, key vKeyID, string msg)
    {
        split2 = msg;
        //llSay(0, kl_listen(0));
        if (llGetSubString(msg, 0, 5) == "MORE (")
        {
            llDialog( vKeyID, dialog_text, klParseButtons( (integer)llGetSubString(msg, 6, 7 ) ), dChannel );
        } else if (kl_listen(0) == "verify")
        {
            if (kl_listen(1) == "" && kl_listen(2) == "" && kl_listen(3) == "")
            {
                llInstantMessage(usrNow, "Missing first name, last name or email.");
            } else {
                llInstantMessage(usrNow, "Please wait...");
                llMessageLinked(LINK_THIS, LINK_COMM, "user:verify|"+ kl_listen(1) +"|"+ kl_listen(2) +"|"+ kl_listen(3), usrNow);
            }
        }
       
        if (msg == "Exit")
        {
            llResetScript();
        }
       
        if (kl_state == "invoice")
        {
            llSetTimerEvent(60);
            kl_state = "invoice_pay";
            list find_instance = [msg];
            integer instance = llListFindList(invoice_name, find_instance);
            invoice_pay_id = llList2String(invoice_id, instance);
            invoice_pay_name = llList2String(invoice_name, instance);
            invoice_pay_amount = llList2String(invoice_amount, instance);
            invoice_pay_linden = llList2String(invoice_linden, instance);
            llMessageLinked(LINK_THIS, LINK_DELAY, "Please pay the terminal within 60 seconds", usrNow);
            llSetPayPrice(PAY_HIDE, [(integer)invoice_pay_linden]);
        }
    }
   
    money(key giver, integer amount) {
        llMessageLinked(LINK_THIS, LINK_COMM, "invoice:pay|"+ userid +"|"+ invoice_pay_id +"|"+ invoice_pay_name +"|"+ (string)amount, usrNow);
        llSetTimerEvent(30);
    }
   
    timer()
    {
        llMessageLinked(LINK_THIS, LINK_DELAY, "Your session has timed out, please restart.", usrNow);
        llResetScript();
    }
}
</lsl>
 
 
Component A
This is where the URL AND php script name/location are stored.
Down in "state http_user" is the url to give if they are not registerd.
 
I STRONGLY advice that you put it in a sub directory with an uneasy guessable name aswell as the php script name so no one can guess where it is located!!
<lsl>
integer LINK_TERM  = 13958260;
integer LINK_COMM  = 13958261;
integer LINK_DELAY  = 13958262;
 
 
string kl_send(string post_option)
{
    requestid = llHTTPRequest(url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], (string)post_option);
    kl_post = "";
    if (DEBUG_post)
    {
        llSay(0, DEBUG_POST);
        DEBUG_POST = "";
    } else {
        DEBUG_POST = "";
    }
    return requestid;
}
 
string kl_clean(string body)
{
    integer clean = 0;
    string cleanbody;
 
    while(llGetSubString(body ,clean,clean))
    {
        cleanbody += llGetSubString(body,clean,clean++);
    }
 
    kl_body = cleanbody;
 
    return kl_body;
}
 
string kl_add(string variable, string value)
{
    string name = variable;
    string message = value;
    if (kl_post == "")
    {
        DEBUG_POST += llEscapeURL(variable) + "=" + llEscapeURL(value);
        kl_post += llEscapeURL(name) + "=" + llEscapeURL(message);
    } else {
        DEBUG_POST += "&" + llEscapeURL(variable) + "=" + llEscapeURL(value);
        kl_post += "&" + llEscapeURL(name) + "=" + llEscapeURL(message);
    }
    return kl_post;
}
 
string kl_list(integer i)
{
    list split = llParseString2List(kl_body, ["|"],[]);
    cmd = llList2String(split, i);
    return cmd;
}
//////////////// END Functions \\\\\\\\\\\\\\\\
 
key requestid;
string url = "http://yoururl.com/whmcs/KLsystem/SecondWHMcs.php";
string kl_body;
string kl_post;
string split;
string cmd;
integer retry = 0;
integer retry_attempt = 0;
 
integer DEBUG_mem = FALSE;
string DEBUG_POST;
integer DEBUG_post = FALSE;
integer DEBUG = FALSE;
 
string body_error;
string kl_state;
 
key usrNow;
string f_name;
string l_name;
string usermail;
string userid;
string invoice_pay_id;
string invoice_pay_name;
string invoice_pay_amount;
 
vector pos;
integer x;
integer y;
integer z;
 
//////////////// END Variables \\\\\\\\\\\\\\\\
 
default
{
    on_rez(integer q)
    {
        llResetScript();
    }
 
    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == LINK_COMM)
        {           
            usrNow = id;
            kl_body = str;
            if (kl_list(0) == "url")
            {
                url = kl_list(1);
            }
           
            if (kl_list(0) == "user:check")
            {
                state user_check;
            }
           
            if (kl_list(0) == "user:verify")
            {
                f_name = kl_list(1);
                l_name = kl_list(2);
                usermail = kl_list(3);
                state user_verify;
            }
           
            if (kl_list(0) == "invoice:check")
            {
                userid = kl_list(1);
                state invoice_check;
            }
           
            if (kl_list(0) == "invoice:pay")
            {
                userid = kl_list(1);
                invoice_pay_id =kl_list(2);
                invoice_pay_name = kl_list(3);
                invoice_pay_amount = kl_list(4);
               
                state invoice_pay;
            }
        }
    }
}
 
state retry_post
{
    state_entry()
    {
        if (kl_state == "user:check") state user_check;
    }
}
 
state http_error_general
{
    state_entry()
    {
        llSay(0, "Something went wrong, please contact support.");
        llOwnerSay("Terminal errors out. "+ kl_body);
        llMessageLinked(LINK_THIS, LINK_TERM, "reset", usrNow);
        llResetScript();
    }
}
 
state http_error
{
    state_entry()
    {
        llMessageLinked(LINK_THIS, LINK_TERM, "error|"+ kl_list(1), "");
        llMessageLinked(LINK_THIS, LINK_TERM, "reset", usrNow);
        llResetScript();
    }
}
 
state user_check
{
    state_entry()
    {
        kl_state = "user:check";
        kl_add("slusername", llKey2Name(usrNow));
        kl_add("sluserkey", usrNow);
        kl_add("option", "user_check");
        kl_send(kl_post);
       
        state http;
    }
}
 
state user_verify
{
    state_entry()
    {
        kl_state = "user:verify";
        kl_add("slusername", llKey2Name(usrNow));
        kl_add("sluserkey", usrNow);
        kl_add("email", usermail);
        kl_add("f_name", f_name);
        kl_add("l_name", l_name);
        kl_add("option", "user_verify");
        kl_send(kl_post);
       
        state http;
    }
}
 
state invoice_check
{
    state_entry()
    {
        kl_state = "invoice:check";
        kl_add("slusername", llKey2Name(usrNow));
        kl_add("sluserkey", usrNow);
        kl_add("userid", userid);
        kl_add("option", "invoice_check");
        kl_send(kl_post);
       
        state http;
    }
}
 
state invoice_pay
{
    state_entry()
    {
        kl_state = "invoice:pay";
        kl_add("slusername", llKey2Name(usrNow));
        kl_add("sluserkey", usrNow);
        kl_add("userid", userid);
        kl_add("invoice_id", invoice_pay_id);
        kl_add("invoice_name", invoice_pay_name);
        kl_add("invoice_amount", invoice_pay_amount);
        kl_add("option", "invoice_pay");
        kl_send(kl_post);
       
        state http;
    }
}
 
//////////////// HTTP \\\\\\\\\\\\\\\\
 
state http
    state_entry()
    {
        llSetTimerEvent(10);
    }
 
    http_response(key request_id, integer status, list metadata, string body)
    {
        if (request_id == requestid)
        {
            if (body == "")
            {
                if (retry_attempt == 0)
                {
                    retry_attempt = 1;
                    state retry_post;
                } else if (retry_attempt == 1) {
                    llWhisper(0, "Something went wrong, please contact for support or try again later.");
                    llResetScript();
                }   
                // END EMPTY BODY CHECK \\
            } else {
                if (DEBUG) llSay(0, body);
            }
            kl_clean(body);
           
            if (kl_list(0) == "error") state http_error;
            if (kl_list(0) == "user") state http_user;
            if (kl_list(0) == "invoice") state http_invoice;
       
            state http_error_general;
        }
    }
   
    timer()
    {
        state retry_post;
    }
   
    state_exit()
    {
        llSetTimerEvent(0);
    }
}
 
//////////////// HTTP Handlers \\\\\\\\\\\\\\\\
 
state http_user
{
    state_entry()
    {
        if (kl_list(1) == "unregisterd")
        {
            llMessageLinked(LINK_THIS, LINK_TERM, "user:unregisterd", usrNow);
            llLoadURL(usrNow, "You must have an account, please follow this url.", "http://yoururl.com/register.php");
            llResetScript();
        }
       
        if (kl_list(1) == "registerd")
        {
            llMessageLinked(LINK_THIS, LINK_TERM, "user:registerd|"+ kl_list(2), usrNow);
            llResetScript();
        }
       
        if (kl_list(1) == "verified")
        {
            llMessageLinked(LINK_THIS, LINK_TERM, "user:verified|"+kl_list(2), usrNow);
        }
       
        llResetScript();
    }
}
 
state http_invoice
{
    state_entry()
    {
        if (kl_list(1) == "list")
        {
            llMessageLinked(LINK_THIS, LINK_TERM, kl_body, usrNow);
        }
       
        if (kl_list(1) == "payed")
        {
            llMessageLinked(LINK_THIS, LINK_TERM, kl_body, usrNow);
        }
        llResetScript();
    }
}
</lsl>
 
 
Component B
<lsl>
integer LINK_TERM  = 13958260;
integer LINK_COMM  = 13958261;
integer LINK_DELAY  = 13958262;
 
 
 
 
string split;
string cmd;
string kl_list(integer i)
{
    list split = llParseString2List(split, ["|"],[]);
    cmd = llList2String(split, i);
    return cmd;
}
 
string str;
key usrNow;
 
default
{
    link_message(integer sender_num, integer num, string str, key id)
    {
        if (num == LINK_DELAY)
        {
            usrNow = id;
            split = str;
            llInstantMessage(usrNow, str);
        }           
    }
}
</lsl>
 
 
Moving on server side, the PHP scripts:
SecondWHMcs.php - you can rename it to what ever you want, the location is in "Component A" script
db_mysql.inc.php - this is the database class, change the username/pass/database in here
 
SecondWHMcs.php:
<lsl>
<?php
 
include("db_mysql.inc.php");
$db = new DB_Sql;
 
define('user_check', 'user_check');
define('user_verify', 'user_verify');
define('invoice_check', 'invoice_check');
 
function gethostbyaddr_timeout($ip,$timeout=2)
{
$host=`host -W $timeout $ip`;
if(preg_match('`in-addr.arpa domain name pointer (.*)\.\n$`i',$host,$matches))
{
$host=$matches[1];
} else {
$host=$ip;
}
return $host;
}
 
$dom = gethostbyaddr_timeout($_SERVER['REMOTE_ADDR']);
$ip = gethostbyname($dom);
if(!preg_match('`^.*\.lindenlab\.com$`',$dom) || $ip!=$_SERVER['REMOTE_ADDR'])
{
print '<center>No outworld access allowed</center>';
exit;
}
 
$exchange = 280;
 
foreach ($_POST as $key => $value) {
$key = $key;
$value = $value;
    $$key = addslashes(trim("$value"));
}
 
 
switch ($option)
{
case user_check:
$sql = 'SELECT id FROM tblclients WHERE sl_name="'.$slusername.'" AND sl_key="'.$sluserkey.'"';
if ($db->query($sql))
{
if ($db->num_rows() == 1)
{
$db->next_record();
print 'user|registerd|'.$db->f("id");
} else {
print 'user|unregisterd';
}
} else {
print 'error|Failed to connect to database, please contact support.';
}
break;
 
case user_verify:
 
$sql = 'SELECT id, firstname, lastname FROM tblclients WHERE email="'.$email.'"';
if ($db->query($sql))
{
if ($db->num_rows() == 1)
{
$db->next_record();
 
if (strtoupper($f_name) == strtoupper($db->f("firstname")) && strtoupper($l_name) == strtoupper($db->f("lastname")))
{
$sql = 'UPDATE tblclients SET sl_name="'.$slusername.'", sl_key="'.$sluserkey.'" WHERE id='.$db->f("id");
if ($db->query($sql))
{
print 'user|verified|'.$db->f("id");
} else {
print 'error|Failed to connect to database, please contact support.';
}
} else {
print 'error|Wrong account info given, please try again.';
}
} else {
print 'error|2Wrong account info given, please try again.';
}
} else {
print 'error|Failed to connect to database, please contact support.';
}
break;
 
case invoice_check:
$sql = 'SELECT id FROM tblclients WHERE id="'.$userid.'" AND sl_name="'.$slusername.'" AND sl_key="'.$sluserkey.'"';
if ($db->query($sql))
{
if ($db->num_rows() == 1)
{
$db->next_record();
if ($db->f("id") == $userid)
{
$sql = 'SELECT tblinvoices.subtotal, tblinvoiceitems.invoiceid, tblinvoiceitems.description FROM tblinvoices LEFT JOIN tblinvoiceitems ON tblinvoices.id WHERE tblinvoices.id=tblinvoiceitems.invoiceid AND tblinvoices.userid="'.$userid.'" AND tblinvoices.status="UnPaid"';
if ($db->query($sql))
{
if ($db->num_rows() > 0)
{
$invoice = 'invoice|list';
$count = 0;
while ($db->next_record())
{
$count++;
$invoice .= '|'.$db->f("invoiceid").'|'.$db->f("description").'|'.$db->f("subtotal");
}
print $invoice;
} else {
print 'error|No invoices found.';
}
} else {
print 'error|Failed to connect to database, please contact support.';
}
} else {
print 'error|No user found, please restart.';
}
} else {
print 'error|No user found, please restart.';
}
} else {
print 'error|Failed to connect to database, please contact support.';
}
break;
 
case invoice_pay:
$sql = 'SELECT id FROM tblclients WHERE id="'.$userid.'" AND sl_name="'.$slusername.'" AND sl_key="'.$sluserkey.'"';
if ($db->query($sql))
{
if ($db->num_rows() == 1)
{
$db->next_record();
if ($db->f("id") == $userid)
{
$sql = 'SELECT tblinvoices.subtotal, tblinvoiceitems.invoiceid, tblinvoiceitems.description FROM tblinvoices LEFT JOIN tblinvoiceitems ON tblinvoices.id WHERE tblinvoices.id=tblinvoiceitems.invoiceid AND tblinvoices.userid="'.$userid.'" AND tblinvoices.status="UnPaid" AND tblinvoiceitems.invoiceid="'.$invoice_id.'" AND tblinvoiceitems.description="'.$invoice_name.'"';
if ($db->query($sql))
{
if ($db->num_rows() == 1)
{
$db->next_record();
$db->query('INSERT INTO tblaccounts (userid, gateway, date, description, amountin, invoiceid) VALUES ("'.$userid.'","banktransfer","'.date('Y-d-m H:i:s', time()).'","Second Life payment: L$ '.$invoice_amount.'  ","'.$db->f("subtotal").'","'.$invoice_id.'")');
$db->query('UPDATE tblinvoices SET status="Paid", datepaid="'.date('Y-d-m H:i:s', time()).'" WHERE userid="'.$userid.'" AND id="'.$invoice_id.'"');
print 'invoice|payed|'.$invoice_name;
} else {
print 'error|No invoice found.';
}
} else {
print 'error|Failed to connect to database, please contact support.';
}
} else {
print 'error|No user found, please restart.';
}
} else {
print 'error|No user found, please restart.';
}
} else {
print 'error|Failed to connect to database, please contact support.';
}
break;
 
default:
//print 'error|Something went wrong, please contact support.';
print 'error|crap...';
 
}
 
?>
</lsl>
 
db_mysql.inc.php:
<lsl>
<?php
/*
* Session Management for PHP3
*
* Copyright (c) 1998-2000 NetUSE AG
*                    Boris Erdmann, Kristian Koehntopp
*
* $Id: db_mysql.inc,v 1.11 2002/08/07 19:33:57 layne_weathers Exp $
*
*/
 
class DB_Sql {
 
  /* public: connection parameters */
  var $Host    = "localhost";
  var $Database = "test";
  var $User    = "UserName";
  var $Password = "PassWord";
 
  /* public: configuration parameters */
  var $Auto_Free    = 0;    ## Set to 1 for automatic mysql_free_result()
  var $Debug        = 0;    ## Set to 1 for debugging messages.
  var $Halt_On_Error = "report"; ## "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore errror, but spit a warning)
  var $PConnect      = 0;    ## Set to 1 to use persistent database connections
  var $Seq_Table    = "db_sequence";
 
  /* public: result array and current row number */
  var $Record  = array();
  var $Row;
 
  /* public: current error number and error text */
  var $Errno    = 0;
  var $Error    = "";
 
  /* public: this is an api revision, not a CVS revision. */
  var $type    = "mysql";
  var $revision = "1.2";
 
  /* private: link and query handles */
  var $Link_ID  = 0;
  var $Query_ID = 0;
 
  var $locked  = false;      ## set to true while we have a lock
 
  /* public: constructor */
  function DB_Sql($query = "") {
      $this->query($query);
  }
 
  /* public: some trivial reporting */
  function link_id() {
    return $this->Link_ID;
  }
 
  function query_id() {
    return $this->Query_ID;
  }
 
  /* public: connection management */
  function connect($Database = "", $Host = "", $User = "", $Password = "") {
    /* Handle defaults */
    if ("" == $Database)
      $Database = $this->Database;
    if ("" == $Host)
      $Host    = $this->Host;
    if ("" == $User)
      $User    = $this->User;
    if ("" == $Password)
      $Password = $this->Password;
     
    /* establish connection, select database */
    if ( 0 == $this->Link_ID ) {
   
      if(!$this->PConnect) {
        $this->Link_ID = mysql_connect($Host, $User, $Password);
      } else {
        $this->Link_ID = mysql_pconnect($Host, $User, $Password);
      }
      if (!$this->Link_ID) {
        $this->halt("connect($Host, $User, \$Password) failed.");
        return 0;
      }
 
      if (!@mysql_select_db($Database,$this->Link_ID)) {
        $this->halt("cannot use database ".$Database);
        return 0;
      }
    }
   
    return $this->Link_ID;
  }
 
  /* public: discard the query result */
  function free() {
      @mysql_free_result($this->Query_ID);
      $this->Query_ID = 0;
  }
 
  /* public: perform a query */
  function query($Query_String) {
    /* No empty queries, please, since PHP4 chokes on them. */
    if ($Query_String == "")
      /* The empty query string is passed on from the constructor,
      * when calling the class without a query, e.g. in situations
      * like these: '$db = new DB_Sql_Subclass;'
      */
      return 0;
 
    if (!$this->connect()) {
      return 0; /* we already complained in connect() about that. */
    };
 
    # New query, discard previous result.
    if ($this->Query_ID) {
      $this->free();
    }
 
    if ($this->Debug)
      printf("Debug: query = %s<br>\n", $Query_String);
 
    $this->Query_ID = @mysql_query($Query_String,$this->Link_ID);
    $this->Row  = 0;
    $this->Errno = mysql_errno();
    $this->Error = mysql_error();
    if (!$this->Query_ID) {
      $this->halt("Invalid SQL: ".$Query_String);
    }
 
    # Will return nada if it fails. That's fine.
    return $this->Query_ID;
  }
 
  /* public: walk result set */
  function next_record() {
    if (!$this->Query_ID) {
      $this->halt("next_record called with no query pending.");
      return 0;
    }
 
    $this->Record = @mysql_fetch_array($this->Query_ID);
    $this->Row  += 1;
    $this->Errno  = mysql_errno();
    $this->Error  = mysql_error();
 
    $stat = is_array($this->Record);
    if (!$stat && $this->Auto_Free) {
      $this->free();
    }
    return $stat;
  }
 
  /* public: position in result set */
  function seek($pos = 0) {
    $status = @mysql_data_seek($this->Query_ID, $pos);
    if ($status)
      $this->Row = $pos;
    else {
      $this->halt("seek($pos) failed: result has ".$this->num_rows()." rows.");
 
      /* half assed attempt to save the day,
      * but do not consider this documented or even
      * desireable behaviour.
      */
      @mysql_data_seek($this->Query_ID, $this->num_rows());
      $this->Row = $this->num_rows();
      return 0;
    }
 
    return 1;
  }
 
  /* public: table locking */
  function lock($table, $mode = "write") {
    $query = "lock tables ";
    if(is_array($table)) {
      while(list($key,$value) = each($table)) {
        // text keys are "read", "read local", "write", "low priority write"
        if(is_int($key)) $key = $mode;
        if(strpos($value, ",")) {
          $query .= str_replace(",", " $key, ", $value) . " $key, ";
        } else {
          $query .= "$value $key, ";
        }
      }
      $query = substr($query, 0, -2);
    } elseif(strpos($table, ",")) {
      $query .= str_replace(",", " $mode, ", $table) . " $mode";
    } else {
      $query .= "$table $mode";
    }
    if(!$this->query($query)) {
      $this->halt("lock() failed.");
      return false;
    }
    $this->locked = true;
    return true;
  }
 
  function unlock() {
 
    // set before unlock to avoid potential loop
    $this->locked = false;
 
    if(!$this->query("unlock tables")) {
      $this->halt("unlock() failed.");
      return false;
    }
    return true;
  }
 
  /* public: evaluate the result (size, width) */
  function affected_rows() {
    return @mysql_affected_rows($this->Link_ID);
  }
 
  function num_rows() {
    return @mysql_num_rows($this->Query_ID);
  }
 
  function num_fields() {
    return @mysql_num_fields($this->Query_ID);
  }
 
  /* public: shorthand notation */
  function nf() {
    return $this->num_rows();
  }
 
  function np() {
    print $this->num_rows();
  }
 
  function f($Name) {
    if (isset($this->Record[$Name])) {
      return $this->Record[$Name];
    }
  }
 
  function p($Name) {
    if (isset($this->Record[$Name])) {
      print $this->Record[$Name];
    }
  }
 
  /* public: sequence numbers */
  function nextid($seq_name) {
    /* if no current lock, lock sequence table */
    if(!$this->locked) {
      if($this->lock($this->Seq_Table)) {
        $locked = true;
      } else {
        $this->halt("cannot lock ".$this->Seq_Table." - has it been created?");
        return 0;
      }
    }
   
    /* get sequence number and increment */
    $q = sprintf("select nextid from %s where seq_name = '%s'",
              $this->Seq_Table,
              $seq_name);
    if(!$this->query($q)) {
      $this->halt('query failed in nextid: '.$q);
      return 0;
    }
   
    /* No current value, make one */
    if(!$this->next_record()) {
      $currentid = 0;
      $q = sprintf("insert into %s values('%s', %s)",
                $this->Seq_Table,
                $seq_name,
                $currentid);
      if(!$this->query($q)) {
        $this->halt('query failed in nextid: '.$q);
        return 0;
      }
    } else {
      $currentid = $this->f("nextid");
    }
    $nextid = $currentid + 1;
    $q = sprintf("update %s set nextid = '%s' where seq_name = '%s'",
              $this->Seq_Table,
              $nextid,
              $seq_name);
    if(!$this->query($q)) {
      $this->halt('query failed in nextid: '.$q);
      return 0;
    }
   
    /* if nextid() locked the sequence table, unlock it */
    if($locked) {
      $this->unlock();
    }
   
    return $nextid;
  }
 
  /* public: return table metadata */
  function metadata($table = "", $full = false) {
    $count = 0;
    $id    = 0;
    $res  = array();
 
    /*
    * Due to compatibility problems with Table we changed the behavior
    * of metadata();
    * depending on $full, metadata returns the following values:
    *
    * - full is false (default):
    * $result[]:
    *  [0]["table"]  table name
    *  [0]["name"]  field name
    *  [0]["type"]  field type
    *  [0]["len"]    field length
    *  [0]["flags"]  field flags
    *
    * - full is true
    * $result[]:
    *  ["num_fields"] number of metadata records
    *  [0]["table"]  table name
    *  [0]["name"]  field name
    *  [0]["type"]  field type
    *  [0]["len"]    field length
    *  [0]["flags"]  field flags
    *  ["meta"][field name]  index of field named "field name"
    *  This last one could be used if you have a field name, but no index.
    *  Test:  if (isset($result['meta']['myfield'])) { ...
    */
 
    // if no $table specified, assume that we are working with a query
    // result
    if ($table) {
      $this->connect();
      $id = @mysql_list_fields($this->Database, $table);
      if (!$id) {
        $this->halt("Metadata query failed.");
        return false;
      }
    } else {
      $id = $this->Query_ID;
      if (!$id) {
        $this->halt("No query specified.");
        return false;
      }
    }
    $count = @mysql_num_fields($id);
 
    // made this IF due to performance (one if is faster than $count if's)
    if (!$full) {
      for ($i=0; $i<$count; $i++) {
        $res[$i]["table"] = @mysql_field_table ($id, $i);
        $res[$i]["name"]  = @mysql_field_name  ($id, $i);
        $res[$i]["type"]  = @mysql_field_type  ($id, $i);
        $res[$i]["len"]  = @mysql_field_len  ($id, $i);
        $res[$i]["flags"] = @mysql_field_flags ($id, $i);
      }
    } else { // full
      $res["num_fields"]= $count;
   
      for ($i=0; $i<$count; $i++) {
        $res[$i]["table"] = @mysql_field_table ($id, $i);
        $res[$i]["name"]  = @mysql_field_name  ($id, $i);
        $res[$i]["type"]  = @mysql_field_type  ($id, $i);
        $res[$i]["len"]  = @mysql_field_len  ($id, $i);
        $res[$i]["flags"] = @mysql_field_flags ($id, $i);
        $res["meta"][$res[$i]["name"]] = $i;
      }
    }
   
    // free the result only if we were called on a table
    if ($table) {
      @mysql_free_result($id);
    }
    return $res;
  }
 
  /* public: find available table names */
  function table_names() {
    $this->connect();
    $h = @mysql_query("show tables", $this->Link_ID);
    $i = 0;
    while ($info = @mysql_fetch_row($h)) {
      $return[$i]["table_name"]      = $info[0];
      $return[$i]["tablespace_name"] = $this->Database;
      $return[$i]["database"]        = $this->Database;
      $i++;
    }
   
    @mysql_free_result($h);
    return $return;
  }
 
  /* private: error handling */
  function halt($msg) {
    $this->Error = @mysql_error($this->Link_ID);
    $this->Errno = @mysql_errno($this->Link_ID);
 
    if ($this->locked) {
      $this->unlock();
    }
 
    if ($this->Halt_On_Error == "no")
      return;
 
    $this->haltmsg($msg);
 
    if ($this->Halt_On_Error != "report")
      die("Session halted.");
  }
 
  function haltmsg($msg) {
    printf("</td></tr></table><b>Database error:</b> %s<br>\n", $msg);
    printf("<b>MySQL Error</b>: %s (%s)<br>\n",
      $this->Errno,
      $this->Error);
  }
 
}
?>
</lsl>
 
I have to stress again that this is old inefficient code but might help you out, now that mono has been released, I`m planning to make a more user friendly general http handler when i get my head to it.

Latest revision as of 11:05, 19 March 2012