OVERVIEW

This set of scripts is designed to run on your own webserver, in order to allow you to easily store and retrieve information from Second Life using the llHTTPRequest() function.  It allows you to store data per Second Life user in field/data pairs.  You don’t have to use it this way, but that’s what it was designed for.

IMPORTANT NOTE

Please remember that this is a free beta.  If you run across minor bugs, please feel free to report them here, and we’ll keep an eye on this project.

DOWNLOAD

DOWNLOAD NOW (.ZIP, 12KB)

CHANGELOG

  • Version 1.02
    • Minor code optimizations
  • Version 1.01
    • Added “secret” parameter for more secure requests
    • Added support for “POST” HTTP Request method
  • Version 1.0
    • Release version

HOW THIS SYSTEM STORES DATA

Each record stored has three variables:  KEY, FIELD, VALUE.

  1. KEY - The key variable is generally designed to store data by SL user keys or uuids. You can use any unique string as a key value, but that’s what it was designed for.
  2. FIELD - This is an identifier for the data you’re storing (such as “length”)
  3. VALUE - And this is the actual information you want to store (such as “21.5″)

For instance, if you were looking to store a particular object’s length, width, and height, (21.5, 10, 0.1) you would store your data as three records:

  • <object uuid>, length, 21.5
  • <object uuid>, width, 10
  • <object uuid>, height, 0.1

where <object uuid> is the Second Life UUID of that particular object.

If you were looking to store a Second Life user’s favorite color, favorite movie, and favorite singer, you might store it like this:

  • <user key>, color, <1,0,0>
  • <user key>, movie, Boondock Saints
  • <user key>, singer, Neil Diamond

where <user key> is the Second Life key for that particular user.

This is about as flexible a storage solution as I could come up with without getting into your individual needs.  If you need something more flexible, you should write your own script (or hire somebody else to).

WHAT YOU’LL NEED

You will need your own hosting account with PHP/MySQL. If you don’t know what those are, go learn and come back when you do. Typically speaking, you can find PHP/MySQL hosting on the cheap (less than $5/mo) all over the place (I recommend http://www.site5.com).

A good rule of thumb is this:  if it will run Wordpress, it should run SLDB just fine.

Most of the detailed instructions here assume you’re running a hosting account with cPanel, but that’s just because I’m lazy and can’t be bothered to learn about other shared hosting setups.  As long as your account has PHP and MySQL, you’re good to go - read the documentation on your hosting account to learn how to set up your MySQL database.

You’ll also need an FTP client of some kind (or cPanel’s File Manager) and know how to use it. It probably wouldn’t hurt to learn how to use phpMyAdmin either, but you don’t need it to set up this script.

You don’t need your own domain name, but this guide assumes you have one, so you’ll need to adjust the instructions accordingly.  Also, domain names are only $10, so cough up and get one, you cheap bastard.

INSTALLATION

This part looks really long, but that’s because there’s a lot of extra details added in for folks who are new to this stuff.  If you’ve ever installed Wordpress, it’s mostly the same stuff, only with less files to upload and less stuff to fill out.

STEP 1: CREATE A MYSQL DATABASE AND USER

You’ll need to create a MySQL database and a user account to manage that database.  If you’re on a cPanel account, this is best accomplished by clicking the “MySQL Database Wizard” icon. Otherwise, follow your hosting service’s instructions.

You should give your user full privileges to the database you create (at the very least SELECT, INSERT, UPDATE, and DELETE). Then make a note of the database name, the user name, and the password.

IMPORTANT: If you have a cPanel account, you should know that your database name is actually a combination of your login name and the name you chose. The same is true of your database username.  So if your username is “dimwit” and you create a database named “sldb” and a user named “sldbadmin” the actual names are “dimwit_sldb” and “dimwit_sldbadmin,” respectively.

Let’s assume your database details are as follows:

Database Name: dimwit_sldb
Database User: dimwit_sldbadmin
Database Pass: sekret

Okay, you’re ready.  Let’s move on to…

STEP 2: EDIT THE FILES

Unzip the files in this package (though chances are you’ve already done that if you’re reading this README) and open “config.php” in your fave plain text editor (if you open it in Microsoft Word, I’ll punch you in the mouth).

Fill out the values listed in that file with the database details you just created.  For the most part, you don’t need to change “localhost.”

You can also select a database table name, though it’s really not necessary.  You can leave the default of “sldb_data.” In fact, if you know enough about PHP/MySQL to NEED to change that value, you should probably be writing your own solution rather than using my crappy one.

The last value in config.php is called “secret.”  This is a passphrase you will define and use in your requests to prevent others from easily posting/fetching data in your database simply by knowing the location of the installation.  Note that this is not exactly military-grade security; if you’re going to be storing sensitive information, you should probably use a more secure custom solution.

STEP 3: UPLOAD THE FILES

Upload the three files (config.php, data.php, and install.php) to a folder on your webserver.  Note the location of this.  For the purposes of this guide, we’ll assume it’s this:

http://www.example.com/sldb/

You don’t have to call the folder sldb, but remember the name of it.

Typically speaking, this folder should go in the /www/ or /public_html/ folder (different for some hosts).

STEP 4: RUN INSTALL.PHP

Visit install.php on your server (in our example, it should be at http://www.example.com/sldb/install.php).

Confirm that you want to install the table.

IMPORTANT: Don’t install twice.  If data already exists in that table, running install.php will wipe it clean.

Once you’re done installing the table, delete the install.php file, like, immediately.

STEP 5: HAVE A MOJITO.  YOU’RE DONE.

BASIC USAGE

Now that you’re all uploaded and stuff, you can store and retrieve data from http://www.example.com/sldb/data.php using llHTTPRequest() (or cURL, but if you knew cURL you probably wouldn’t need this, so I’ll skip that stuff).

The fastest way to use this is by using the example.lsl script included in the package.  This script includes three custom functions you can call to store/retrieve/delete data in various ways.  Just copy the functions into the top of your LSL script (along with a couple of required variables) and you’ll be ready to go, or use the example to make your own adjustments. However, it’s good, on the whole, to know how the system works, so we’re including a guide here.

NOTE: The rest of this section is going to look really daunting, but remember that this is only really necessary if you want to use the system for more advanced applications.  If you’re only looking to store/save a few user preferences, the LSL example is much simpler and easy to use. Read on once you’ve given the example a shot if you think you might need a more involved understanding of how this works.

UNDERSTANDING HTTP GET REQUESTS

The LSL example handles most of this for you, but it’s a good idea to understand just what this system is doing.

Essentially, when you send an HTTP request, you’re reading a really simple web page created by the web app.  In order for the web app to know what kind of data to put on the page, it uses certain bits of data included in the URL of the page you’re requesting.

A simple GET request URL looks like this:

http://example.com/page.php?parameter1=value1&parameter2=value2

The web app grabs the parameter1 = value1 part and the parameter2 = value2 part and uses those values to create the page with the data you need. So a sample request for this particular app may look like this:

http://example.com/sldb/data.php?key=a27b84f0-2757-4176-9579-43a181d4a5a0&fields=length|width|height&action=get&secret=mypassphrase

This requests tells the web app to “get” (action=get) the values for length, width, and height (fields=length|width|height) assigned to the user key a27b84f0-2757-4176-9579-43a181d4a5a0 (key=a27b84f0-2757-4176-9579-43a181d4a5a0) and authenticates the request with your passphrase (secret=mypassphrase).

Once you get how this works, it’s just a matter of knowing what parameters to include in your http request.

PARAMETERS

You can do one of three things with these requests: add/update data (put), retrieve values (get), or remove data (del). You can update, retrieve, or delete multiple fields at once.

The SLDB web app accepts the following parameters:

  • KEY (key) - Each record is assigned to a “key,” a unique string (no more than 36 characters long) that identifies the “owner” of that data.This key can be an avatar’s UUID (most common), an object UUID (less useful), or even a random value determined by you to identify that set of values.The key allows you to store multiple field/value pairs in a single context (such as field/value pairs for each user of an object).
  • SEPARATOR (separator) - When sending fields/values to the web app, you need a character (or combination of characters) to separate values in a list.  For instance, this string: length|width|height
    is a list of fields (length, width, and height) separated by the character “|”.The default separator is the pipe (”|”) and the web app will use this character if you have not defined a separator. We use the pipe as the default because your data may already contain commas, which would make parsing results difficult.  However, if you’d like to use a different separator, such as “||” (double pipe) or “*” (asterisk) you may do so. The web app will parse your list using your custom separator and return it using the separator, so it’s best to define your separator as a global variable to avoid confusion (as seen in the LSL example). Use a separator character that will NOT appear in your field names or values.
  • FIELDS (fields) - These are the names of the fields you’re looking to update, delete, or retrieve, separated by the separator (for instance: length|width|height).If you’re retrieving data, it will be returned in the same order as the given request.
  • VALUES (values) - These are the values you’re looking to assign to the fields, in the same order as the field names.  Like the fields parameter, the values should be sent in a list separated by the same character you have defined as your separator (for instance: 21.5|15|0.1).Note that all data will be typecasted to strings, so you’ll need to re-cast your retrieved data to use it.  In other words, if you’re storing the vector <1,2,3> it will return as a string “<1.000, 2.000, 3.000>” so you’ll want to use the (vector) typecast to read it when retrieving it from the server.
  • ACTION (action) - The action parameter defines what it is you want the web app to do with the data it’s being sent. There are three possible values for this:
    • action=put - The “put” action stores your field/value pair.  If a value already exists for any given field, it will be overwritten with the new value.
    • action=get - The “get” action retrieves the values for a given list of fields, and will return the list of values in the same order as the fields requested.
    • action=del - The “del” action deletes the the values for a given list of fields. Note that the actions that write to/delete from the database are, by nature, irreversible; you will need to manually re-write values or delete written values to undo these actions.
  • REVERSE (reverse) - If set to “reverse=true”, “reverse=yes”, or “reverse=1″, the action you’re taking (either get or del) will be reversed.  For instance, if you want to retrieve the field names of certain values (instead of the values for certain field names), use “reverse=true” and a list of values instead of fields in order to return the set of field names.  The same goes for “del;” if you want to delete certain records based on the values and NOT the field names, use “reverse=true” and provide values instead of field names.  Note that when using reverse, you’ll need to provide exact values, as the web app uses “value=<data>” instead of “CONTAINS %<data>%.” Again, this web app is designed for simplicity, so if you need a more flexible solution you’ll probably need to write one yourself.
  • VERBOSE (verbose) - The verbose parameter (”verbose=true” or “verbose=yes” or “verbose=1″) will return more verbose results from your queries.  For instance, if you send a request to update these fields: length|width|height with these values: “21.5|10,0.1″ you will by default get the message “SUCCESS:3″ which indicates you have successfully updated 3 records.  If verbose is enabled, the response will be “SUCCESS: UPDATED 3 RECORDS.” In this way, verbose is good for debugging (more user-readable) but harder to parse.When requesting data, however, the verbose option becomes more important. By default, the server returns only the values you’ve requested in the same order by which they were requested (for instance, requesting “length|width|height” would return “21.5|10|0.1″).  With verbose enabled, it returns a list with the field names included (for instance: “length|21.5|width|10|height|0.1″). This is handy if you don’t want to hold the current list of fields you’re fetching, and would rather be able to parse the values directly from the http_response.
  • SECRET (secret) - The secret parameter is a required parameter and should match the one set in your config.php file.  This authenticates the request.

ALL_DATA AND NO_DATA

There are two custom strings used by the web app: ALL_DATA and NO_DATA. ALL_DATA is something you can send to the server in your get and del requests to instruct the web app to either get or delete all fields for a given key.  Send the list ["ALL_DATA"] from your LSL script to accomplish this.

Note that if you’re using the get action, it’s better to use verbose when requesting ALL_DATA, as there will be no other way to figure out which value corresponds to which field name otherwise.  Also, if you have a lot of fields stored for each key, it’s probably a bad idea to use ALL_DATA to fetch; LSL can only accept strings so long, and you might only get a part of your data back because of this.

NO_DATA is something the server returns if there is no data set for a particular field you’re requesting data from.  For instance, if you have nothing set in the “width” field and you request “length|width|height” you’ll get something like this: “21.5|NO_DATA|1.0″.

RESPONSES AND ERROR MESSAGES

When retrieving data, the server will respond with either the data you’ve requested or (if something is afoul) an “ERROR:” message.  When storing or deleting data, the server will respond with a SUCCESS:” message, followed by the number of records affected by your request.  There are only a handful of error messages you can get, and these are as follows:

  • ERROR: INSTALL FILE NOT DELETED - You must delete the install.php file after you have installed SLDB.  It is so important, in fact, that the rest of the web app has been designed not to work until this has been done.  If you get this message, go delete the install.php from your server using your FTP client.
  • ERROR: CANNOT CONNECT TO DATABASE - This means that either your MySQL services are offline or (more commonly) the MySQL username/password combination you’ve provided in config.php is not correct.
  • ERROR: CANNOT SELECT DATABASE - This indicates that the web app was able to connect to your MySQL services (the user/pass combination is fine) but it cannot find the database you’ve named in config.php.
  • ERROR: INSUFFICIENT ARGUMENTS - This indicates that you’ve sent a request that is lacking the necessary parameters.  You may have forgotten to put a key value in the request, for instance, or to name your fields.
  • ERROR: UNMATCHED PARAMETERS - This message only occurs in storage (put) requests, and indicates that the number of field names you have provided does not match the number of values you’ve provided.  For instance, if you tried to update [length,width,height] with [21.5,10] you’ll get this error because you’ve only got two values for three arguments.
  • ERROR: SYNTAX - This message indicates some kind of fatal problem with the web app’s MySQL syntax.  If you get this, and you haven’t been messing around with the php code, it’s probably my fault, so tell me in the comments.  If you have been messing around with the php code, go back and check your adjustments, because MySQL is getting syntax commands it doesn’t understand.
  • ERROR: CANNOT CONNECT TO SERVER - This error is actually defined in the example LSL script, so if you’ve changed it, it’ll be different.  This indicates that the LSL script could not connect to your server at all, and most commonly means you’ve entered the wrong URL in your HTTP request.

TIPS & TRICKS

Here are a few tips and tricks for using the system to fullest advantage.  We’ll add more when we think of some.

  • If you submit a float to the PutData() function (the custom function included in the LSL example), remember that LSL will automatically stretch out the decimal places on a vector.  In other words, if you submit [1.5] as a value, this will be stored to the database as “1.500000″ because LSL distends this float before converting it to a string.  If this is a problem for you (it shouldn’t be unless you’re using the data for text displays), do your own string conversion (["1.5"]) before sending it to the function.
  • You don’t have to use UUIDs or SL avatar keys for the “key” parameter.  This is the most ubiquitous usage of the “key” parameter, which is why we suggest it as a default, but any unique string will do.  You could use an avatar’s name, or a group name, or a product name - the “key” parameter is simply a way of grouping sets of fields together so that you can have multiple instances of the same field for different users, objects, or applications.
  • You don’t have to use one database for all your needs; simply install another instance of SLDB (connected to another database) in a different directory.  MySQL databases are cheap (most accounts come with unlimited databases), so there’s no discernible reason not to set up multiple databases for different applications.
  • BACK UP YOUR DATABASES.  It’s easy to back up a MySQL database, and the resulting backup is usually tiny.  If your hosting provider has a control panel (like cPanel or Plesk) there’s usually an option right in the control panel.  If they don’t, you can use phpMyAdmin.  Regular database backups are like colonoscopies; they may be a pain in the ass, but by the time you realize you should have had one, it’s too late.
  • BACK UP YOUR DATABASES.  This bears repeating.
  • When possible, group your requests so as to retrieve multiple fields using the same llHTTPRequest , rather than running one request for each field.  These requests aren’t particularly resource-heavy, but it’s just good server hygiene to get the most out of your server traffic.