65ce40036a
When `mysqli_connect` fails, `$link` becomes false, and the `or` branch is taken, which uses `mysqli_error($link)`, which in turn fails because `$link` is false. Since it's correctly checking `mysqli_connect_errno()` in the next line, just removing the `or` suffices. Per report by jonhboy Resident.
325 lines
12 KiB
PHP
325 lines
12 KiB
PHP
<?php
|
|
|
|
/*
|
|
MIT License
|
|
|
|
Copyright (c) the AVsitter Contributors (http://avsitter.github.io)
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
|
|
header("Content-Type: text/plain; charset=utf-8");
|
|
|
|
error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
|
ini_set('display_errors', '1');
|
|
|
|
require_once("settings-config.inc.php");
|
|
|
|
$link = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
|
|
|
|
if (mysqli_connect_errno()) {
|
|
die ("Connect failed: " . mysqli_connect_error());
|
|
}
|
|
// Set the character set for communication with the database
|
|
if (!mysqli_set_charset($link, 'utf8mb4')) {
|
|
die('Invalid charset: utf8mb4');
|
|
}
|
|
|
|
// Pre-escape $avpos_table for convenience. That's the only variable
|
|
// that should go directly into a query. All others should go through
|
|
// IntSQL or StrSQL as appropriate.
|
|
$avpos_table = IdentSQL($avpos_table);
|
|
|
|
undo_magic_quotes($_REQUEST);
|
|
|
|
if($_REQUEST['action']=="install" && $allow_install==true){
|
|
$sql = "DROP TABLE IF EXISTS $avpos_table;";
|
|
$result = mysqli_query($link,$sql) or die("Error creating table: ".mysqli_error($link));
|
|
$sql = "CREATE TABLE IF NOT EXISTS $avpos_table (
|
|
`id` int(11) NOT NULL auto_increment,
|
|
`webkey` varchar(36) default NULL,
|
|
`owner_uuid` varchar(36) default NULL,
|
|
`owner_name` varchar(63) default NULL,
|
|
`text` TEXT CHARSET utf8mb4 default NULL,
|
|
`keep` tinyint(1) default 0,
|
|
`count` int(5) default NULL,
|
|
`ip` varbinary(16) default NULL,
|
|
`timestamp` datetime NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE (`webkey`)
|
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;";
|
|
$result = mysqli_query($link,$sql) or die("Error formatting table: ".mysqli_error($link));
|
|
if($result) {
|
|
echo "Your tables have been formatted!";
|
|
}
|
|
else{
|
|
echo "Oops! There were some problems. You should check your config and try again: ".mysqli_error($link);
|
|
}
|
|
}
|
|
else if(isset($_REQUEST['w'])){ // write to a record
|
|
$given_webkey = $_REQUEST['w'];
|
|
|
|
$ip_address = $_SERVER['REMOTE_ADDR'];
|
|
$ip_packed = inet_pton($ip_address);
|
|
|
|
if(!isValidGuid($given_webkey)){
|
|
echo "INVALID WEBKEY";
|
|
}
|
|
else{
|
|
$owner_key = $_SERVER['HTTP_X_SECONDLIFE_OWNER_KEY'];
|
|
//$object_name = $_SERVER['HTTP_X_SECONDLIFE_OBJECT_NAME'];
|
|
$owner_name = $_SERVER['HTTP_X_SECONDLIFE_OWNER_NAME'];
|
|
//$object_key = $_SERVER['HTTP_X_SECONDLIFE_OBJECT_KEY'];
|
|
//$region = trim(substr($_SERVER['HTTP_X_SECONDLIFE_REGION'],0,strrpos($_SERVER['HTTP_X_SECONDLIFE_REGION'],'(')));
|
|
//$position_array = explode(', ',substr($_SERVER['HTTP_X_SECONDLIFE_LOCAL_POSITION'],1,-1));
|
|
//$slurl = rawurlencode($region) . "/" . round($position_array[0]) . "/" . round($position_array[1]) . "/" . round($position_array[2]);
|
|
|
|
if(!isValidGuid($owner_key)){
|
|
echo "INVALID USER";
|
|
}
|
|
else{
|
|
$given_count = intval($_REQUEST['c']);
|
|
$given_text = $_REQUEST['t'];
|
|
|
|
$sql = "SELECT * FROM $avpos_table"
|
|
. ' WHERE webkey = ' . StrSQL($given_webkey);
|
|
|
|
$result = mysqli_query($link,$sql) or email_death("ERR01: " . mysqli_error($link));
|
|
if(mysqli_num_rows($result) == 0){ // a new webkey
|
|
if($given_count == 1){
|
|
if(!isAllowedIP($ip_address)){
|
|
$response = "BAD IP";
|
|
$sql = "INSERT INTO $avpos_table"
|
|
. ' (owner_uuid,owner_name,webkey,text,count,ip,timestamp)'
|
|
. ' VALUES '
|
|
. '(' . StrSQL($owner_key)
|
|
. ',' . StrSQL($owner_name)
|
|
. ',' . StrSQL($given_webkey)
|
|
. ',' . StrSQL("The IP address of the sim ($ip_address) was not in the allowed range. Please report the problem if you think this is in error")
|
|
. ',10001'
|
|
. ',' . StrSQL($ip_packed)
|
|
. ',NOW()'
|
|
. ')';
|
|
}
|
|
else{
|
|
$response = "ADDED NEW";
|
|
if(endsWith($_REQUEST['t'],"\n\nend")){
|
|
$given_count+=10000;
|
|
$response = "FINISHING";
|
|
}
|
|
$sql = "INSERT INTO $avpos_table"
|
|
. ' (owner_uuid,owner_name,webkey,text,count,ip,timestamp)'
|
|
. ' VALUES '
|
|
. '(' . StrSQL($owner_key)
|
|
. ',' . StrSQL($owner_name)
|
|
. ',' . StrSQL($given_webkey)
|
|
. ',' . StrSQL($given_text)
|
|
. ',' . IntSQL($given_count)
|
|
. ',' . StrSQL($ip_packed)
|
|
. ',NOW()'
|
|
. ')';
|
|
}
|
|
$result = mysqli_query($link,$sql) or email_death("ERR02: " . mysqli_error($link));
|
|
}
|
|
else{
|
|
$response = "WRONG COUNT";
|
|
}
|
|
}
|
|
else{ // an existing webkey
|
|
if(!isAllowedIP($ip_address)){
|
|
$response = "BAD IP";
|
|
}
|
|
else{
|
|
$row = mysqli_fetch_assoc($result);
|
|
$newtext = $row['text'] . $given_text;
|
|
if (strlen($newtext) > 65535) {
|
|
$sql = "UPDATE $avpos_table"
|
|
. ' SET text = ' . StrSQL("64K limit exceeded.\n"
|
|
. "The text that was generated can't"
|
|
. " be saved as a notecard because it's"
|
|
. " too long.")
|
|
. ', count = ' . IntSQL(10000+$given_count)
|
|
. ', timestamp = NOW()'
|
|
. ' WHERE webkey = ' . StrSQL($given_webkey);
|
|
mysqli_query($link,$sql) or email_death("ERR03: " . mysqli_error($link));
|
|
$response = "NOTECARD TOO LONG";
|
|
}
|
|
else if (startsWith($newtext, '64K limit exceeded')) {
|
|
$response = "NOTECARD TOO LONG";
|
|
}
|
|
else if($row['count']+1 == $given_count){
|
|
$response = "ADDING";
|
|
|
|
if(endsWith($_REQUEST['t'],"\n\nend")){
|
|
$given_count+=10000;
|
|
$response = "FINISHING";
|
|
}
|
|
|
|
$sql = "UPDATE $avpos_table"
|
|
. ' SET text = ' . StrSQL($newtext)
|
|
. ', count = ' . IntSQL($given_count)
|
|
. ', timestamp = NOW()'
|
|
. ' WHERE webkey = ' . StrSQL($given_webkey);
|
|
$result = mysqli_query($link,$sql) or email_death("ERR03: " . mysqli_error($link));
|
|
|
|
}
|
|
else{
|
|
$response = "WRONG COUNT";
|
|
}
|
|
}
|
|
}
|
|
echo $response;
|
|
}
|
|
}
|
|
}
|
|
else if(isset($_REQUEST['q'])){ // read a record
|
|
|
|
$out = "";
|
|
|
|
$given_webkey = $_REQUEST['q'];
|
|
$sql = "SELECT * FROM $avpos_table"
|
|
. ' WHERE webkey = ' . StrSQL($given_webkey);
|
|
|
|
$result = mysqli_query($link,$sql) or email_death("ERR04: " . mysqli_error($link));
|
|
if(mysqli_num_rows($result) == 0){
|
|
$out= "Not found. Expired links are deleted.";
|
|
}
|
|
else{
|
|
$row = mysqli_fetch_assoc($result);
|
|
if($row['count']>10000){
|
|
$out.= $row['text'];
|
|
|
|
if(1==2){ // switch on to 'keep' any record that ever was accessed
|
|
$sql = "UPDATE $avpos_table"
|
|
. ' SET keep = 1'
|
|
. ' WHERE webkey = ' . StrSQL($given_webkey);
|
|
$result = mysqli_query($link,$sql) or email_death("ERR05: " . mysqli_error($link));
|
|
}
|
|
|
|
// delete all entries older than 10 minutes that are not flagged keep
|
|
$sql = "DELETE FROM $avpos_table"
|
|
. ' WHERE timestamp < DATE_SUB(NOW(), INTERVAL 10 MINUTE)'
|
|
. ' AND keep = 0';
|
|
$result = mysqli_query($link,$sql) or email_death("ERR06: " . mysqli_error($link));
|
|
|
|
}
|
|
else{
|
|
$out.="Data was incomplete, please try again.\n\nThis feature is new and experimental - you're welcome to report any issues.";
|
|
}
|
|
}
|
|
echo $out;
|
|
}
|
|
else{
|
|
header('HTTP/1.0 400 Bad Request');
|
|
die("400 Bad Request: No valid action specified.");
|
|
}
|
|
|
|
function undo_magic_quotes(&$var)
|
|
{
|
|
// Does anyone still use these? Probably not but just in case.
|
|
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
|
|
{
|
|
// This doesn't remove the slashes in the keys, but that doesn't matter for us.
|
|
foreach ($var as $k => &$v)
|
|
{
|
|
if (is_array($v))
|
|
undo_magic_quotes($v);
|
|
else
|
|
$v = stripslashes($v);
|
|
}
|
|
}
|
|
}
|
|
|
|
function IdentSQL($str){
|
|
return '`' . str_replace('`', '``', $str) . '`';
|
|
}
|
|
|
|
function StrSQL($str){
|
|
if ($str === null)
|
|
return "NULL";
|
|
return "'" . mysqli_real_escape_string($GLOBALS['link'], strval($str)) . "'";
|
|
}
|
|
|
|
function IntSQL($int){
|
|
return strval(intval($int));
|
|
}
|
|
|
|
function isValidGuid($guid){
|
|
return !empty($guid) && preg_match('/^\{?[a-zA-Z0-9]{8}(?:-[a-zA-Z0-9]{4}){4}[a-zA-Z0-9]{8}\}?$/', $guid);
|
|
}
|
|
|
|
function email_death($error){
|
|
$body="\n";
|
|
$body.="\n\$_SERVER\n";
|
|
foreach($_SERVER as $key_name => $key_value) {
|
|
$body.= $key_name . " = " . $key_value . "\n";
|
|
}
|
|
$body.="\n\$_GET\n";
|
|
foreach($_GET as $key_name => $key_value) {
|
|
$body.= $key_name . " = " . $key_value . "\n";
|
|
}
|
|
$body.="\n\$_POST\n";
|
|
foreach($_POST as $key_name => $key_value) {
|
|
$body.= $key_name . " = " . $key_value . "\n";
|
|
}
|
|
$to = $GLOBALS['email_to'];
|
|
$subject = "avsitter: $error";
|
|
$email_headers = "From: ". $GLOBALS['email_from'] ."\r\n" . "X-Mailer: php";
|
|
mail($to, $subject, $body, $email_headers);
|
|
die($error);
|
|
}
|
|
|
|
function startsWith($haystack, $needle) {
|
|
// search backwards starting from haystack length characters from the end
|
|
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
|
|
}
|
|
|
|
function endsWith($haystack, $needle) {
|
|
// search forward starting from end minus needle length characters
|
|
return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== FALSE);
|
|
}
|
|
|
|
function isAllowedIP($ip){
|
|
if($GLOBALS['check_ip']==false){
|
|
return true;
|
|
}
|
|
$llsubnets = array(
|
|
"8.2.32.0/22",
|
|
"8.4.128.0/22",
|
|
"8.10.144.0/21",
|
|
"63.210.156.0/22",
|
|
"64.154.220.0/22",
|
|
"216.82.0.0/18"
|
|
);
|
|
foreach($llsubnets as $range){
|
|
if(ip_in_range($ip,$range)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// check if an ip_address in a particular range
|
|
function ip_in_range( $ip, $range ) {
|
|
// $range is in IP/CIDR format eg 127.0.0.1/24
|
|
list( $range, $netmask ) = explode( '/', $range, 2 );
|
|
$range_decimal = ip2long( $range );
|
|
$ip_decimal = ip2long( $ip );
|
|
$wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1;
|
|
$netmask_decimal = ~ $wildcard_decimal;
|
|
return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) );
|
|
}
|