W-Hat
postcardscontact
faq
httpdb provides free, persistant, off-site storage for Second Life LSL Scripts via llHTTPRequest. You can store up to 250kb of data in the form of key/value pairs, and read or write the data from any script. You can share your data with other users, protect it with passwords, browse and manage your data on the web, and download backups.
There is no need to register to use httpdb, you can just start saving and retrieving data at any time. There are some advanced features that require you to set an admin password; see Advanced Use.
string HTTPDB = "http://w-hat.com/httpdb/"; // httpdb url
key reqid_load; // request id
// Save a value to httpdb with the specified name.
httpdb_save( string name, string value ) {
llHTTPRequest( HTTPDB + name, [HTTP_METHOD, "PUT"], value );
}
// Load named data from httpdb.
httpdb_load( string name ) {
reqid_load = llHTTPRequest( HTTPDB + name, [HTTP_METHOD, "GET"], "" );
}
default {
http_response( key reqid, integer status, list meta, string body ) {
if ( reqid == reqid_load ) {
// do something with body
}
}
}
For more complete library code, see libhttpdb.lsl.
All httpdb requests are composed of three parts: a path, a method,
and a body. These correspond directly to the three parameters of
llHTTPRequest
A path is a "name" or "key" that identifies a value. You specify
the path you want to access by adding it on to the httpdb URL, and
using it as the first parameter of llHTTPRequest. For
example, the URL for a value called myproject/data1.txt
would be http://w-hat.com/httpdb/myproject/data1.txt.
httpdb uses the HTTP Request Method to determine what action you
want to perform. GET is for retrieving data, PUT is for saving data,
DELETE is for removing data, and POST is used for updating metadata.
You specify the method by passing [HTTP_METHOD,
"(method)"] as the second parameter of
llHTTPRequest.
The body of the request is the third parameter of
llHTTPRequest. It should be blank for GET and DELETE
requests, but for PUT requests it should contain the actual data that
you want to store.
httpdb uses a subset of the standard HTTP 1.1 responses, with slightly adapted semantics:
200 OK
Sent when a request succeeded. For GET requests, the body is the value of the requested data. For PUT and DELETE requests, the body is the updated amount of free space remaining.
201 Created
Sent in response to PUT when the request succeeded and a new path was created. The body is the updated amount of free space remaining.
400 Bad Request
Sent when you make a request that does not make any sense; for example, using mode=append with GET.
403 Forbidden
Sent when you do not have sufficent permission or the correct password to do what you are attempting.
404 Not Found
Sent when you attempt to GET or DELETE a path that doesn't exist.
413 Request Entity Too Large
Sent when you do not have enough free space available to store the body of a PUT request.
500 Internal Server Error
Sent when something went wrong. Please send an IM to Masakazu Kojima in-world if you receive this.
For quick checking, a code < 300 means success, and a code >= 400 means error.
You can add options to a request in the normal HTTP way: append a
question mark (?) to the URL, and then a list of "key=value" pairs
separated by "and" symbols (&). Each option has a shorthand version
displayed after it in parenthesis that you can use instead of the full
name. For example:
http://w-hat.com/httpdb/secret?m=read&password=hello
mode (m)
The 'mode' option controls the way the specified request is carried out.
PUT
GET
start (s)
LSL truncates the body of HTTP responses that are too long. When
this happens, the metadata parameter of the http_response event will
contain [HTTP_BODY_TRUNCATED, amount], where
amount is the position it was truncated.
In order to read the rest of the data, you must repeat the request and supply this parameter. httpdb will skip the specified number of bytes at the beginning of the data.
password (p)
If the operation you are trying to perform requires a password, you must provide it with this option.
read_password (rp) [PUT, POST only]
This option sets the password required for read access to the specified data (GET requests). This applies to both the owner of the data and others trying to access it.
You can set this freely when creating new records, but to change
the password on existing records, you must provide your admin password
with the password parameter.
write_password (writepass, wp) [PUT, POST only]
The same as read_password, but for writing (PUT and DELETE requests).
Paths beginning with two underscores are reserved for system use.
__/
The __/ directory is used to share data, and access
data belonging to other users, by supplying the key of the owner in
the format that llGetOwner() and other LSL functions provide it (with
dashes and lowercase letters). For example, to access my data, you
would use
http://w-hat.com/httpdb/__/a27b84f0-2757-4176-9579-43a181d4a5a0/.
If you know someone's name, but not their key, you can use name2key to look it up.
Only you can create records in your shared directory. Anything you
create that is not in this directory is private, and cannot be
accessed by scripts belonging to other users. __/me/ is a
shortcut to your own shared directory.
__sys/space/free, __sys/space/used, __sys/space/available
Contains the amount of space free, used, and available in total, respectively, in bytes. Read-only.
__sys/admin_password
This value controls your admin password, which is used to log in to the website, change properties, and can override any other password. By default you do not have an admin password, and nothing will be accepted for it.
If you GET this value, you will be sent an IM in Second Life containing a randomly-generated password that can be used to PUT a new value here. The randomly-generated password cannot be used for anything else, and does not affect your existing admin password. Once you have an admin password set, you can use it to change this value, or you can repeat the process if you forget it.
__sys/defaults
If you set a read_password or write_password on this record (using PUT or POST), they will used for all records that do not have their own. Additionally, the write_password applied to this record is required to create any new records.
You can use POST to change the metadata associated with a record
without changing the record itself. You pass a list of options in the
normal format, but as the body of the request instead of after a
question mark in the URL. You must provide your admin password as the
password parameter. For example, to change the password
on 'top/secret.txt' you would do:
llHTTPRequest(
"http://w-hat.com/top/secret.txt", [HTTP_METHOD, "POST"], "password=" +
admin_pass + "&wp=sekrit");
After logging into the Web Interface, you can download CSV dumps of all your data. The dump contains the following information for each record (in this order): path, creator, created_at, updater, updated_at, read_password, write_password, data. The passwords are salted MD5 hashes, the same way they are stored in the database.
You can access any part of the Web Interface
from scripts outside of SL. The username parameter is called login
and the password parameter is called password. You can
use this to set up a cronjob on your computer to download backups,
or whatever you want.
There are about 250 bytes of overhead for each record, used for metadata, paths, and indexing. This means that even if you only store one byte, it will be counted as much more. This also means it is more economical to use a few large records, rather than many small records.
The space limit is per SL account, so you can use any alternate accounts you have for more space. Additional storage can be arranged; send an IM to Masakazu Kojima in world for more information.
Ease of Use
While experienced developers can probably create and start using an SQL database in no time, someone who only knows LSL probably could not. SQL would also require additional setup steps (creating a database, creating a table), so you wouldn't be able to just jump in and start using it. Experienced developers should have access to their own server anyway.
Returning SQL results in a way that LSL can understand would also be a challenge. While a special format could be used to safely return the data as a list of lists, this would be yet another intellectual barrier to entry and require extra "library" code to use the service. Nevermind that, given LSL's performance, it could take all day to make heads or tails of a reply.
Security
Allowing the general public to execute arbitary SQL queries poses a serious security risk. While there are many limits and restrictions that could be imposed, they would make sharing data difficult and many "ordinary" queries would have to be rejected or cut off.
Carl Omlet offers free, unlimited(?) storage through llHTTPRequest().
Some Jerk offers a bad attitude and a false sense of security.
Zero Linden created Silo, "a simple, general purpose file system for LSL via HTTP" written in PHP. It is similar to httpdb and you host it yourself. (link fixed 2006-11-04)
These examples use libhttpdb.lsl.
Visitor Logger
float SCAN_RANGE = 32.0;
float SCAN_INTERVAL = 30.0;
httpdb_success( integer type, string name, integer status ) {
if ( status == 201 ) { // new record created, first visit
list l = llParseString2List( name, "/" ); // [ "visitors", key ]
key id = llList2String( l, 1 );
// greet them
llInstantMessage( id, "WELCOME TO THE INTERNET!" );
}
}
default {
state_entry() {
llSensorRepeat("", NULL_KEY, AGENT, SCAN_RANGE, PI, SCAN_INTERVAL);
}
sensor(integer num) {
integer i = num;
while (i--) {
httpdb_save(
"visitors/" + (string)llDetectedKey(i),
llGetTimestamp()
);
}
}
}
Log File
log(string message) {
string logstr = "[" + llGetTimestamp() + "] " + message;
llOwnerSay(logstr);
httpdb_save( "logs/example.log?mode=prepend", logstr + "\n" );
}
High Score List
Customer List
Name2key Database
Server Tracker (objdns)
XML-RPC Key Tracker