hash($key);
$sql = sprintf('insert into ownership (`name`, `key`, `email`, `last_login`, `created`, `updated`) values ("%s", "%s", "%s", NOW(), NOW(), NOW())', mysql_real_escape_string($name), mysql_real_escape_string($key), mysql_real_escape_string($email));
$result = mysql_query($sql);
// (4) created account
if ($result) {
$ok = true;
$created = true;
// echo json_encode(array('ok' => true, 'created' => true));
} else {
echo json_encode(array('ok' => false, 'message' => 'Something went wrong when I tried to create your account :-\\', 'error' => mysql_error(), 'step' => '3'));
}
// (1) ERROR - user name doesn't exist
} else if (!$email && !$home && !$rows_found) {
// log in attempt when username wasn't found
echo json_encode(array('ok' => false, 'message' => "No dice I'm afraid, those details didn't work.", 'step' => '1'));
// (2) user was found with that name
} else if ($rows_found) {
// check key
$row = mysql_fetch_object($result);
$saved_email = $row->email;
$hashed = $row->key;
$saved_name = $row->name;
$created = date_parse($row->created);
// (2.1) account hasn't been updated to bcrypt
if (!$created || $created['warning_count']) {
// (2.1.1) sha1 matches
if ($hashed === sha1($key)) {
$hashed = $bcrypt->hash($key);
$sql = sprintf('UPDATE ownership SET `key`="%s", `last_login`=NOW(), `created`=NOW(), `updated`=NOW() WHERE `name`="%s"', mysql_real_escape_string($hashed), mysql_real_escape_string($name));
if (!mysql_query($sql)) {
echo json_encode(array('ok' => false, 'error' => mysql_error(), 'step' => '2.1.1'));
exit;
}
}
}
if ($home) {
$ok = true;
if ($email) {
$saved_email = $email;
$sql = sprintf('UPDATE ownership SET `email`="%s" WHERE `name`="%s"', mysql_real_escape_string($email), mysql_real_escape_string($name));
if (!mysql_query($sql)) {
echo json_encode(array('ok' => false, 'error' => mysql_error(), 'step' => '5.1'));
exit;
}
}
if ($key) {
$saved_email = $email;
$sql = sprintf('UPDATE ownership SET `key`="%s" WHERE `name`="%s"', mysql_real_escape_string($bcrypt->hash($key)), mysql_real_escape_string($name));
if (!mysql_query($sql)) {
echo json_encode(array('ok' => false, 'error' => mysql_error(), 'step' => '5.2'));
exit;
}
}
// (2.2) check bcrypt passsowrd matches
} else if ($bcrypt->verify($key, $hashed)) {
// otherwise username & password were okay, update their details (including email addy)
$ok = true;
$sql = sprintf('UPDATE ownership SET `last_login`=NOW() WHERE `name`="%s"', mysql_real_escape_string($name));
// (2.2.1) logged in, also update their email address
if ($email && $home) {
$sql = sprintf('UPDATE ownership SET `email`="%s", `last_login`=NOW() WHERE `name`="%s"', mysql_real_escape_string($email), mysql_real_escape_string($name));
$saved_email = $email;
}
if (!mysql_query($sql)) {
echo json_encode(array('ok' => false, 'error' => mysql_error(), 'step' => '2.2.1'));
exit;
}
} else {
// (2.3) found username, but the password didn't match
if ($email && !$home) {
echo json_encode(array('ok' => false, 'message' => "Too late I'm afraid, that username is taken.", 'step' => '2.3'));
// (2.4) password doesn't match
} else {
echo json_encode(array('ok' => false, 'message' => "No dice I'm afraid, those details didn't work.", 'step' => '2.4'));
}
}
} else {
// (6) trying to change username - we don't support this yet
if ($home && $home != $saved_name && !$rows_found) {
// trying to change their username - not supported yet.
echo json_encode(array('ok' => false, 'message' => "Sorry, changing your username isn't supported just yet. We're on it though!", 'step' => '6'));
} else {
echo json_encode(array('ok' => false, 'message' => "Ooh, this is embarrassing. Something's failed and I'm not quite sure what..."));
}
}
if ($ok) {
setSession($name, $saved_email);
if ($home) {
echo json_encode(array('ok' => true, 'message' => 'Account updated.'));
} else {
echo json_encode(array('ok' => true, 'created' => $created));
}
}
exit;
}
// disabling - not sure this looks right
} else if (FALSE && ($action == 'updatehome' && $_SERVER['REQUEST_METHOD'] == 'POST')) {
$key = isset($_POST['key']) ? trim($_POST['key']) : null;
$email = isset($_POST['email']) ? trim($_POST['email']) : null;
$set = array();
if (!$home) {
exit;
}
if ($email) {
array_push($set, '`email`="' . mysql_real_escape_string($email) . '"');
}
if ($key) {
$bcrypt = new Bcrypt(10);
$hashed = $bcrypt->hash($key);
array_push($set, '`key`="' . mysql_real_escape_string($hashed) . '"');
}
if (!mysql_query(sprintf('UPDATE ownership SET %s WHERE `name`="%s"', implode($set, ', '), mysql_real_escape_string($home)))) {
header("HTTP/1.1 500 Internal Server Error");
echo json_encode(array('ok' => false, 'error' => mysql_error()));
exit;
}
if ($ajax) {
echo json_encode(array('ok' => true, 'error' => false));
} else {
header('Location: ' . PATH);
}
exit;
} else if ($action == 'forgot') {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = isset($_POST['email']) ? trim($_POST['email']) : null;
if (!$email) {
echo json_encode(array('error' => 'Please provide a valid email address'));
exit;
} else {
$sql = 'SELECT * FROM `ownership` WHERE `email`="%s" LIMIT 1';
$sql = sprintf($sql, mysql_real_escape_string($email));
$result = mysql_query($sql);
if (!mysql_num_rows($result)) {
echo json_encode(array('error' => 'Unable to find a user for that email'));
header("HTTP/1.1 404 Not Found");
exit;
}
$user = mysql_fetch_object($result);
$token = md5(rand());
$expires = date('Y-m-d H:i:s', time() + (24 * 60 * 60));
$sql = 'INSERT INTO `forgot_tokens` (`owner_name`, `token`, `expires`, `created`) VALUES ("%s", "%s", "%s", NOW())';
$sql = sprintf($sql, mysql_real_escape_string($user->name), $token, $expires);
if (!mysql_query($sql)) {
header("HTTP/1.1 500 Internal Server Error");
echo json_encode(array('ok' => false, 'error' => mysql_error()));
exit;
}
$view = file_get_contents('../views/reset_email.txt');
$mustache = new Mustache;
$mail_body = $mustache->render($view, array(
'link' => ROOT . '/reset?token=' . $token,
'domain' => $_SERVER['SERVER_NAME']
));
$result = mail($user->email, 'JSBin Password Reset', $mail_body, 'From: JSBin
is replaced. // FIXME there's still a bug here if appears in the script and not in the // markup - but I'll fix that later if (!$quiet && !$download) { $html = str_lreplace('', '' . "\n", $html); } if ($no_code_found == false && !$download) { $html = str_lreplace('', googleAnalytics() . '', $html); } if (false) { if (stripos($html, '
')) { $html = preg_replace('/
(.*)/', '
$1', $html);
} else {
// if we can't find a head element, brute force the framebusting in to the HTML
$html = '' . $html;
}
}
if (!$html && !$ajax) {
$javascript = "/*\n Created using " . ROOT . "\n Source can be edit via " . $host . ROOT . "$code_id/edit\n*/\n\n" . $javascript;
}
if (!$html) {
header("Content-type: text/javascript");
}
if ($last_updated) {
header("Last-Modified: " . date('r', strtotime($last_updated)));
}
echo $html ? $html : $javascript;
$edit_mode = false;
}
}
if (!$edit_mode || $ajax) {
exit;
}
function connect() {
// sniff, and if on my mac...
$link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME, $link);
}
function encode($s) {
static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $s) . '"';
}
function str_lreplace($search, $replace, $subject) {
$pos = strrpos($subject, $search);
if ($pos === false) {
return $subject;
} else {
return substr_replace($subject, $replace, $pos, strlen($search));
}
}
function setSession($name, $email) {
$data = json_encode(array('user' => array(
'name' => $name,
'email' => $email,
'lastLogin' => time()
)));
$hash = session_hash($data);
setcookie('session', $hash . $data, time() + 60 * 60 * 24 * 30, PATH);
}
function getCodeIdParams($request) {
global $home;
$revision = array_pop($request);
$code_id = array_pop($request);
if ($code_id == null || ($home && $home == $code_id)) {
$code_id = $revision;
$revision = 1;
}
return array($code_id, $revision);
}
function getMaxRevision($code_id) {
$sql = sprintf('select max(revision) as rev from sandbox where url="%s"', mysql_real_escape_string($code_id));
$result = mysql_query($sql);
$row = mysql_fetch_object($result);
return $row->rev ? $row->rev : 0;
}
function formatCompletedCode($html, $javascript, $css, $code_id, $revision) {
global $ajax, $quiet;
$javascript = preg_replace('@window.onfocus=function(){return false;};window.open=window.print=window.confirm=window.prompt=window.alert=function(){};' . $html;
}
if ($html && stripos($html, '%code%') === false && strlen($javascript)) {
$close = '';
if (stripos($html, '') !== false) {
$parts = explode("", $html);
$html = $parts[0];
$close = count($parts) == 2 ? '' . $parts[1] : '';
}
$html .= "\n" . $close;
} else if ($javascript) {
// removed the regex completely to try to protect $n variables in JavaScript
$htmlParts = explode("%code%", $html);
$html = $htmlParts[0] . $javascript . $htmlParts[1];
$html = preg_replace("/%code%/", $javascript, $html);
}
// repeat for CSS
if ($html && stripos($html, '%css%') === false && strlen($css)) {
$close = '';
if (stripos($html, '') !== false) {
$parts = explode("", $html);
$html = $parts[0];
$close = count($parts) == 2 ? '' . $parts[1] : '';
}
$html .= "\n" . $close;
} else if ($css) {
// TODO decide whether this is required for the JS
// removed the regex completely to try to protect $n variables in JavaScript
$htmlParts = explode("%css%", $html);
$html = $htmlParts[0] . $css . $htmlParts[1];
$html = preg_replace("/%css%/", $css, $html);
}
if (!$ajax && $code_id != 'jsbin') {
$code_id .= $revision == 1 ? '' : '/' . $revision;
$html = preg_replace('/", $html);
}
return array($html, $javascript, $css);
}
function getCode($code_id, $revision, $testonly = false) {
$sql = sprintf('select * from sandbox where url="%s" and revision="%s"', mysql_real_escape_string($code_id), mysql_real_escape_string($revision));
$result = mysql_query($sql);
if (!mysql_num_rows($result) && $testonly == false) {
header("HTTP/1.1 404 Not Found");
return defaultCode(true);
} else if (!mysql_num_rows($result)) {
return array($revision);
} else {
$row = mysql_fetch_object($result);
// TODO required anymore? used for auto deletion
$sql = 'update sandbox set last_viewed=now() where id=' . $row->id;
mysql_query($sql);
$javascript = preg_replace('/\r/', '', $row->javascript);
$html = preg_replace('/\r/', '', $row->html);
$css = preg_replace('/\r/', '', $row->css);
$revision = $row->revision;
// this is hack, but it's the easiest way of getting the timestamp out
global $last_updated;
$last_updated = $row->created;
// return array(preg_replace('/\r/', '', $html), preg_replace('/\r/', '', $javascript), $row->streaming, $row->active_tab, $row->active_cursor);
return array($revision, get_magic_quotes_gpc() ? stripslashes($html) : $html, get_magic_quotes_gpc() ? stripslashes($javascript) : $javascript, get_magic_quotes_gpc() ? stripslashes($css) : $css);
}
}
function defaultCode($not_found = false) {
$library = '';
global $no_code_found;
if ($not_found) {
$no_code_found = true;
}
$usingRequest = false;
if (isset($_REQUEST['html']) || isset($_REQUEST['js']) || isset($_REQUEST['javascript'])) {
$usingRequest = true;
}
if (@$_REQUEST['html']) {
$html = $_REQUEST['html'];
} else if ($usingRequest) {
$html = '';
} else {
$html = getDefaultCode('html');
}
$javascript = '';
if (@$_REQUEST['js']) {
$javascript = $_REQUEST['js'];
} else if (@$_REQUEST['javascript']) {
$javascript = $_REQUEST['javascript']; // it's beyond me why I ever used js?
} else if ($usingRequest) {
$javascript = '';
} else {
if ($not_found) {
$javascript = 'document.getElementById("hello").innerHTML = "This URL does not have any code saved to it.";';
} else {
$javascript = getDefaultCode('javascript');
}
}
$css = '';
if (@$_REQUEST['css']) {
$css = $_REQUEST['css'];
} else {
$css = getDefaultCode('css');
}
return array(0, get_magic_quotes_gpc() ? stripslashes($html) : $html, get_magic_quotes_gpc() ? stripslashes($javascript) : $javascript, get_magic_quotes_gpc() ? stripslashes($css) : $css);
}
function getDefaultCode($prop) {
global $custom;
$ext = $prop === 'javascript' ? 'js' : $prop;
$custom_filename = isset($custom['__dirname']) ? ($custom['__dirname'] . 'default.' . $ext) : null;
$default_filename = '../views/default.' . $ext;
$code = '';
if (file_exists($custom_filename)) {
$code = file_get_contents($custom_filename);
}
else if (file_exists($default_filename)) {
$code = file_get_contents($default_filename);
}
return $code;
}
// I'd consider using a tinyurl type generator, but I've yet to find one.
// this method also produces *pronousable* urls
function generateCodeId($tries = 0) {
$code_id = generateURL();
if ($tries > 2) {
$code_id .= $tries;
}
// check if it's free
$sql = sprintf('select id from sandbox where url="%s"', mysql_real_escape_string($code_id));
$result = mysql_query($sql);
if (mysql_num_rows($result)) {
$code_id = generateCodeId(++$tries);
} else if ($tries > 10) {
echo('Too many tries to find a new code_id - please contact using about');
exit;
}
return $code_id;
}
function generateURL() {
// generates 5 char word
$vowels = str_split('aeiou');
$const = str_split('bcdfghjklmnpqrstvwxyz');
$word = '';
for ($i = 0; $i < 6; $i++) {
if ($i % 2 == 0) { // even = vowels
$word .= $vowels[rand(0, 4)];
} else {
$word .= $const[rand(0, 20)];
}
}
return $word;
}
function googleAnalytics() {
global $quiet;
if (!$quiet) {
return <<