From 08bbd3f9127204aa4bc8be18fdc6ca6d68d88ff1 Mon Sep 17 00:00:00 2001 From: Savetheinternet Date: Wed, 6 Apr 2011 18:31:26 +1000 Subject: [PATCH] Post saving/cache and Google Analytics integration --- inc/config.php | 16 +++++++++++++++- inc/display.php | 16 ++++++++++++---- main.js | 37 ++++++++++++++++++++++++++++++++++++- mod.php | 18 ++++++++++++++++++ post.php | 10 ++++++++++ templates/main.js | 42 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 131 insertions(+), 8 deletions(-) diff --git a/inc/config.php b/inc/config.php index b3c69faa..2e6389c9 100644 --- a/inc/config.php +++ b/inc/config.php @@ -47,6 +47,9 @@ $config['cookies']['hash'] = 'hash'; // Used for moderation login $config['cookies']['mod'] = 'mod'; + // Used for communicating with Javascript; telling it when posts were successful + // Currently DO NOT CHANGE THIS OR IT WON'T WORK! + $config['cookies']['js'] = 'serv'; // Cookies "path". Defaults to $config['root']. If $config['root'] is a URL, you need to set this. Should be '/' or '/board/', depending on your installation. // $config['cookies']['path'] = '/'; // Where to set the 'path' parameter to $config['cookies']['path'] when creating cookies. Recommended. @@ -104,6 +107,8 @@ $config['error']['youaremuted'] = 'You are muted! Expires in %d seconds.'; $config['error']['tor'] = 'Hmm… That looks like a Tor exit node.'; $config['error']['toomanylinks'] = 'Too many links; flood detected.'; + $config['error']['toomanycites'] = 'Too many cites; post discarded.'; + $config['error']['toomanycross'] = 'Too many cross-board links; post discarded.'; $config['error']['nodelete'] = 'You didn\'t select anything to delete.'; $config['error']['noreport'] = 'You didn\'t select anything to report.'; $config['error']['toomanyreports'] = 'You can\'t report that many posts at once.'; @@ -133,7 +138,7 @@ $config['report_limit'] = 2; // How long before you can delete a post after posting, in seconds. - $config['delete_time'] = 60; + $config['delete_time'] = 10; // Reply limit (stops bumping thread when this is reached) $config['reply_limit'] = 250; @@ -153,6 +158,10 @@ $config['block_tor'] = true; // Typically spambots try to post a lot of links. Refuse a post with X standalone links? $config['max_links'] = 20; + // Maximum number of cites per post (protects against abuse) + $config['max_cites'] = 45; + // Maximum number of cross-board links/cites per post + $config['max_cross'] = $config['max_cites']; // Maximum image upload size in bytes $config['max_filesize'] = 10*1024*1024; // 10MB @@ -266,6 +275,8 @@ $config['mod']['ban_message'] = '(%s)'; // Wait indefinitely when rebuilding everything $config['mod']['rebuild_timelimit'] = 0; + // Server-side confirm button for actions like deleting posts, for when Javascript is disabled or the DOM isn't loaded. + $config['mod']['server-side_confirm'] = true; // Probably best not to change these: if(!defined('JANITOR')) { @@ -513,4 +524,7 @@ // Meta keywords. It's probably best to include these in per-board configurations. //$config['meta_keywords'] = 'chan,anonymous discussion,imageboard,tinyboard'; + + // Link imageboard to your Google Analytics account to track users and provide marketing insights. + // $config['google_analytics'] = 'UA-xxxxxxx-yy'; ?> \ No newline at end of file diff --git a/inc/display.php b/inc/display.php index 88976457..72983a49 100644 --- a/inc/display.php +++ b/inc/display.php @@ -92,6 +92,14 @@ ))); } + function confirmLink($text, $title, $confirm, $href) { + global $config, $mod; + if($config['mod']['server-side_confirm']) + return '' . $text . ''; + else + return '' . $text . ''; + } + class Post { public function __construct($id, $thread, $subject, $email, $name, $trip, $body, $time, $thumb, $thumbx, $thumby, $file, $filex, $filey, $filesize, $filename, $ip, $root=null, $mod=false) { global $config; @@ -136,11 +144,11 @@ // Delete if($this->mod['type'] >= $config['mod']['delete']) - $built .= ' ' . $config['mod']['link_delete'] . ''; + $built .= ' ' . confirmLink($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['uri'] . '/delete/' . $this->id); // Delete all posts by IP if($this->mod['type'] >= $config['mod']['deletebyip']) - $built .= ' ' . $config['mod']['link_deletebyip'] . ''; + $built .= ' ' . confirmLink($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by IP?', $board['uri'] . '/deletebyip/' . $this->id); // Ban if($this->mod['type'] >= $config['mod']['ban']) @@ -283,11 +291,11 @@ // Delete if($this->mod['type'] >= $config['mod']['delete']) - $built .= ' ' . $config['mod']['link_delete'] . ''; + $built .= ' ' . confirmLink($config['mod']['link_delete'], 'Delete', 'Are you sure you want to delete this?', $board['uri'] . '/delete/' . $this->id); // Delete all posts by IP if($this->mod['type'] >= $config['mod']['deletebyip']) - $built .= ' ' . $config['mod']['link_deletebyip'] . ''; + $built .= ' ' . confirmLink($config['mod']['link_deletebyip'], 'Delete all posts by IP', 'Are you sure you want to delete all posts by IP?', $board['uri'] . '/deletebyip/' . $this->id); // Ban if($this->mod['type'] >= $config['mod']['ban']) diff --git a/main.js b/main.js index d434acb3..cef82687 100644 --- a/main.js +++ b/main.js @@ -1,3 +1,12 @@ +function get_cookie(cookie_name) +{ + var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)'); + if(results) + return (unescape(results[2])); + else + return null; +} + function highlightReply(id) { var divs = document.getElementsByTagName('div'); @@ -33,6 +42,9 @@ function dopost(form) { if(form.email.value != 'sage') localStorage.email = form.email.value; + saved[document.location] = form.body.value; + sessionStorage.body = JSON.stringify(saved); + return form.body.value != "" || (typeof form.thread != "undefined" && form.file.value != ""); } function citeReply(id) { @@ -44,6 +56,7 @@ var styles = [ ['Yotsuba B', '/board/default.css'], ['Yotsuba', '/board/yotsuba.css'] ]; +var saved = {}; function changeStyle(x) { localStorage.stylesheet = styles[x][1]; @@ -92,6 +105,28 @@ function init() if(localStorage.email) document.getElementsByTagName('form')[0].email.value = localStorage.email; + + if(sessionStorage.body) { + saved = JSON.parse(sessionStorage.body); + if(get_cookie('serv')) { + // Remove successful posts + successful = JSON.parse(get_cookie('serv')); + for (var url in successful) { + saved[url] = null; + } + sessionStorage.body = JSON.stringify(saved); + + document.cookie = 'serv={};expires=0;path=/;'; + } + if(saved[document.location]) { + document.getElementsByTagName('form')[0].body.value = saved[document.location]; + } + } + + if(localStorage.body) { + document.getElementsByTagName('form')[0].body.value = localStorage.body; + localStorage.body = ''; + } link = document.getElementsByTagName('a'); for ( i in link ) { if(typeof link[i] == "object" && link[i].childNodes[0].src) { @@ -120,4 +155,4 @@ function init() } } -window.onload = init; \ No newline at end of file +window.onload = init; diff --git a/mod.php b/mod.php index c7ee054b..15a602c2 100644 --- a/mod.php +++ b/mod.php @@ -174,6 +174,24 @@ destroyCookies(); header('Location: ?/', true, $config['redirect_http']); + } elseif(preg_match('/^\/confirm\/(.+)$/', $query, $matches)) { + $uri = $matches[1]; + + $body = '

' . + 'Are you sure you want to do that?' . + 'You clicked ' . + '?/' . htmlentities($uri) . '' . + ' but had Javascript disabled, so we weren\'t able to serve the confirmation dialog.' . + '

' . + '

Confirm.

'; + + echo Element('page.html', Array( + 'config'=>$config, + 'title'=>'Confirm', + 'body'=>$body, + 'mod'=>true + ) + ); } elseif(preg_match('/^\/log$/', $query)) { if($mod['type'] < $config['mod']['modlog']) error($config['error']['noaccess']); diff --git a/post.php b/post.php index faa4cecc..88bdf3ae 100644 --- a/post.php +++ b/post.php @@ -460,6 +460,16 @@ buildIndex(); sql_close(); + // Tell Javascript that we posted successfully + if(isset($_COOKIE[$config['cookies']['js']])) + $js = json_decode($_COOKIE[$config['cookies']['js']]); + else + $js = Array(); + // Tell it to delete the cached post for referer + $js->{$_SERVER['HTTP_REFERER']} = true; + // Encode and set cookie + setcookie($config['cookies']['js'], json_encode($js), 0, $config['cookies']['jail']?$config['cookies']['path']:'/', null, false, false); + $root = $post['mod'] ? $config['root'] . $config['file_mod'] . '?/' : $config['root']; if($config['always_noko'] || $noko) { diff --git a/templates/main.js b/templates/main.js index 7bf5b6d9..296e5c07 100644 --- a/templates/main.js +++ b/templates/main.js @@ -1,3 +1,12 @@ +function get_cookie(cookie_name) +{ + var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)'); + if(results) + return (unescape(results[2])); + else + return null; +} + function highlightReply(id) { var divs = document.getElementsByTagName('div'); @@ -20,7 +29,7 @@ function focusId(id) function generatePassword() { pass = ''; - chars = '{config[genpassword_chars]}'; + chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+'; for(i=0;i<8;i++) { rnd = Math.floor(Math.random() * chars.length); pass += chars.substring(rnd,rnd + 1); @@ -33,6 +42,9 @@ function dopost(form) { if(form.email.value != 'sage') localStorage.email = form.email.value; + saved[document.location] = form.body.value; + sessionStorage.body = JSON.stringify(saved); + return form.body.value != "" || (typeof form.thread != "undefined" && form.file.value != ""); } function citeReply(id) { @@ -44,6 +56,7 @@ var styles = [ {stylesheets:['{stylesheets[name]}', '{stylesheets[uri]}']{!%last?, }} ]; +var saved = {}; function changeStyle(x) { localStorage.stylesheet = styles[x][1]; @@ -92,6 +105,28 @@ function init() if(localStorage.email) document.getElementsByTagName('form')[0].email.value = localStorage.email; + + if(sessionStorage.body) { + saved = JSON.parse(sessionStorage.body); + if(get_cookie('{config[cookies][js]}')) { + // Remove successful posts + successful = JSON.parse(get_cookie('{config[cookies][js]}')); + for (var url in successful) { + saved[url] = null; + } + sessionStorage.body = JSON.stringify(saved); + + document.cookie = '{config[cookies][js]}={};expires=0;path=/;'; + } + if(saved[document.location]) { + document.getElementsByTagName('form')[0].body.value = saved[document.location]; + } + } + + if(localStorage.body) { + document.getElementsByTagName('form')[0].body.value = localStorage.body; + localStorage.body = ''; + } link = document.getElementsByTagName('a'); for ( i in link ) { if(typeof link[i] == "object" && link[i].childNodes[0].src) { @@ -120,4 +155,7 @@ function init() } } -window.onload = init; \ No newline at end of file +window.onload = init; +{config[google_analytics]? + +var _gaq = _gaq || [];_gaq.push(['_setAccount', '{config[google_analytics]}']);_gaq.push(['_setDomainName', 'none']);_gaq.push(['_trackPageview']);(function() {var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);})();} \ No newline at end of file