diff --git a/adhoc.js b/adhoc.js index 3789f73..3d61028 100644 --- a/adhoc.js +++ b/adhoc.js @@ -5,6 +5,21 @@ Event.KEY_COMMAND2 = 93; Event.KEY_COMMAND3 = 224; Event.KEY_SPACE = 32; +// Add handling for scroll wheel +Object.extend(Event, { + wheel: function(e){ + e = e || window.event; + var delta = 0; + if(e.wheelDelta){ + delta = e.wheelDelta/120; + if(window.opera) delta *= -1; + }else if(e.detail){ + delta = e.detail / -3; + } + return Math.round(delta); + } +}); + // Not sure why JavaScript doesn't include this... String.prototype.ltrim = function(s){ return this.replace(new RegExp("^"+s+"+"), ""); @@ -1116,6 +1131,7 @@ Event.observe(window, 'load', function(){ } // Validate string values adhoc.validateString = function(v){ + if(v == "") return false; var escaped = v.replace(/\\./g, ''); if(escaped.indexOf('"') >= 0) return 'Must escape double-quotes: \\"'; @@ -3439,6 +3455,14 @@ Event.observe(window, 'load', function(){ adhoc.display_y = starty + startpy - Event.pointerY(e); adhoc.refreshRender(); }; + // Handle mouse wheel + var wheelFunc = function(e){ + if(Event.wheel(e) == 1){ + adhoc.zoomIn(); + }else{ + adhoc.zoomOut(); + } + } // Handle key down var keyDownFunc = function(e){ var key = e.which || window.event.keyCode; @@ -3797,6 +3821,8 @@ Event.observe(window, 'load', function(){ adhoc.canvas.observe('touchend', upFunc); adhoc.canvas.observe('mousemove', moveFunc); adhoc.canvas.observe('touchmove', moveFunc); + Event.observe(adhoc.canvas, 'mousewheel', wheelFunc); + Event.observe(adhoc.canvas, 'DOMMouseScroll', wheelFunc); Event.observe(window, 'keydown', keyDownFunc); Event.observe(window, 'keyup', keyUpFunc); @@ -3827,6 +3853,42 @@ Event.observe(window, 'load', function(){ $('histBack').observe('click', adhoc.history.undo); $('histFwd').observe('click', adhoc.history.redo); + // Create pulse function to keep sessions alive + setInterval(function(){ + if(adhoc.setting('username')){ + new Ajax.Request('keepalive/', { + parameters: { + username: adhoc.setting('username') + ,passhash: adhoc.setting('password') + ,xsrftoken: $('xsrfToken').innerHTML + } + ,onSuccess: function(t){ + if(t.responseText){ + $('xsrfToken').update(t.responseText); + } + } + ,onFailure: function(t){ + if(t.responseText){ + $('xsrfToken').update(t.responseText); + }else{ + adhoc.error('Your session may have expired. Try clicking here to login in another tab'); + } + } + }); + } + }, 10*60*1000); + + // Handle window close + Event.observe(window, 'beforeunload', function(e){ + if($('savePackageButton').hasClassName('disabled') + || adhoc.history.index==0 + ) return true; + var msg = "You have unsaved changes. Are you sure you want to close the page?"; + var evt = e || window.event; + if(evt) evt.returnValue = msg; + return msg; + }); + // Bind to the window window.adhoc = adhoc; } @@ -4496,7 +4558,7 @@ Event.observe(window, 'load', function(){ ctx.strokeRect( (n.x-(n.width/2.0)) * adhoc.display_scale - adhoc.display_x ,(n.y-(n.height/2.0)) * adhoc.display_scale - adhoc.display_y - ,(size.width+10) * adhoc.display_scale + ,size.width + 10 * adhoc.display_scale ,20 * adhoc.display_scale ); } @@ -4510,13 +4572,13 @@ Event.observe(window, 'load', function(){ var size = ctx.measureText(n.id); ctx.fillText( n.id - ,(n.x+(n.width/2.0)-(size.width+5)) * adhoc.display_scale - adhoc.display_x + ,(n.x+(n.width/2.0)-5) * adhoc.display_scale - size.width - adhoc.display_x ,(n.y+(n.height/2.0)-6) * adhoc.display_scale - adhoc.display_y ); ctx.strokeRect( - (n.x+(n.width/2.0)-(size.width+10)) * adhoc.display_scale - adhoc.display_x + (n.x+(n.width/2.0)-10) * adhoc.display_scale - size.width - adhoc.display_x ,(n.y+(n.height/2.0)-20) * adhoc.display_scale - adhoc.display_y - ,(size.width+10) * adhoc.display_scale + ,size.width + 10 * adhoc.display_scale ,20 * adhoc.display_scale ); } @@ -4766,7 +4828,7 @@ Event.observe(window, 'load', function(){ adhoc.foldNode = function(n){ if(!n.children.length) return; n.folded = !n.folded; - adhoc.refreshRender(); + adhoc.snapToNode(n); } // Zooms the view in adhoc.zoomIn = function(){ diff --git a/analyze/index.php b/analyze/index.php index dc55303..2260218 100644 --- a/analyze/index.php +++ b/analyze/index.php @@ -17,12 +17,12 @@ $errors = array(); // Weights for different factors -$weight_totalLoops = 1.0; -$weight_maxLoopNest = 1.0; -$weight_condReturns = 1.0; -$weight_actionVerb = 3.0; -$weight_nodeCount = 0.1; -$weight_paramCount = 1.0; +$weight_totalLoops = 4.0; +$weight_maxLoopNest = 6.0; +$weight_condReturns = 3.0; +$weight_actionVerb = 5.0; +$weight_nodeCount = 0.05; +$weight_paramCount = 3.0; $weight_childCount = 1.0; $weight_inputsVoid = 0.5; $weight_inputsBool = 0.5; @@ -34,7 +34,7 @@ $weight_inputsStruct = 0.5; $weight_inputsAction = 0.5; $weight_inputsMixed = 0.5; -$weight_outputType = 1.0; +$weight_outputType = 3.0; $scale_diffSegmenting = 5; // Start the session @@ -109,7 +109,7 @@ FLOOR(data.diff / ?) ASC ,data.isConfirmed DESC ,data.diff ASC - LIMIT 5; "; + LIMIT 10; "; $query = mysqli_stmt_init($dbConn); if(!mysqli_stmt_prepare($query, $sql)){ $errors[] = "Could not prepare database statement: ".$dbConn->error; diff --git a/keepalive/index.php b/keepalive/index.php new file mode 100644 index 0000000..9133379 --- /dev/null +++ b/keepalive/index.php @@ -0,0 +1,110 @@ +error){ + $errors[] = $dbConn->error; + $dbConn = null; +} + +// If already logged in, pass back the current XSRF token, or make a new one +if(isset($_SESSION['username'])){ + if($_SESSION['username']==$_POST['username']){ + if(!isset($_SESSION['xsrftoken'])) + $_SESSION['xsrftoken'] = sha1(rand().$_SESSION['username']); + exit($_SESSION['xsrftoken']); + }else{ + http_response_code(401); + exit; + } +} + +// Try to log the user in +if(!isset($_POST['username']) || !$_POST['username']){ + http_response_code(401); + exit; +} +if(!isset($_POST['password']) || !$_POST['password']){ + http_response_code(401); + exit; +} + +// Try to fetch the user +$query = mysqli_stmt_init($dbConn); +if(!count($errors) && !mysqli_stmt_prepare($query, " + SELECT + username + ,settings + FROM + front_users + WHERE + username = ? + AND password = UNHEX(?) + LIMIT + 1; ")){ + $errors[] = "Could not prepare database statement: ".$dbConn->error; +} +if(!count($errors) && !mysqli_stmt_bind_param($query, 'ss' + ,$_POST['username'] + ,sha1(sha1($_POST['password'])) + )){ + $errors[] = "Could not bind database parameters: ".$query->error; +} +if(!count($errors) && !mysqli_stmt_execute($query)){ + $errors[] = "Query failed: ".$query->error; +} +if(!count($errors) && !mysqli_stmt_bind_result($query + ,$username + ,$settingsTemp + )){ + $errors[] = "Query failed: ".$query->error; +} +if(!count($errors) && !$query->fetch()){ + $errors[] = "Could not load user"; +} + +// Add password back to settings (if requested) and pass settings in the cookie +if(!count($errors)){ + $_SESSION['username'] = $username; + if($_POST['remember']=='1'){ + $settingsTemp = json_decode($settingsTemp); + $settingsTemp->password = sha1($_POST['password']); + $settingsTemp = json_encode($settingsTemp); + } + setcookie( + 'adhocSettings' + ,$settingsTemp + ,strtotime('+1 year') + ,'/adhoc_demo/' + ,'' + ); + if(!isset($_SESSION['xsrftoken'])) + $_SESSION['xsrftoken'] = sha1(rand().$_SESSION['username']); + exit($_SESSION['xsrftoken']); +}else{ + http_response_code(401); + exit; +} diff --git a/login/index.php b/login/index.php index 717a590..a918bc2 100644 --- a/login/index.php +++ b/login/index.php @@ -39,7 +39,7 @@ exit; } -// If registration was submitted, try to register the user +// If login was submitted, try to log the user in if(isset($_POST['submitted'])){ // Get the user credentials from input if(!isset($_POST['username']) || !$_POST['username']){ @@ -56,7 +56,7 @@ $settings->username = $_POST['username']; $settings->remember = ($_POST['remember']=='1'); - // Try to create the user + // Try to fetch the user $query = mysqli_stmt_init($dbConn); if(!count($errors) && !mysqli_stmt_prepare($query, " SELECT diff --git a/style.css b/style.css index 42da67e..a4e4129 100644 --- a/style.css +++ b/style.css @@ -138,13 +138,15 @@ label { box-sizing:border-box; float:left; max-height:400px; - overflow-y:visible; + overflow-y:scroll; width:30%; } .graftListItem { + border-bottom:1px solid; box-sizing:border-box; cursor:pointer; float:left; + padding:8px 0; width:100%; } .graftListItem.selected {