From 22a5ddc1156bd6e78fb5dc528cfc19dc38180275 Mon Sep 17 00:00:00 2001 From: xevidos Date: Wed, 10 Apr 2019 19:31:28 -0400 Subject: [PATCH] Added get all user options function, Continued work on SQL library, Fixed issue where project was not loaded from settings, Improved performance for getting all options, Refactored install process to fit with new library, Refactored active module to use SQL, Fixed issue where a non focused file could not be closed when first logged in, Fixed issue of text mode not being selected after renaming a file, --- components/active/class.active.php | 353 ++++++++++++----------- components/active/init.js | 5 +- components/autosave/init.js | 12 +- components/editor/init.js | 18 +- components/install/install.php | 129 +++++++-- components/install/process.php | 295 ------------------- components/install/sql/mysql.sql | 57 ---- components/install/sql/pgsql.sql | 53 ---- components/install/sql/sqlite.sql | 53 ---- components/install/view.php | 9 +- components/project/init.js | 1 + components/settings/class.settings.php | 30 ++ components/settings/controller.php | 6 + components/settings/init.js | 25 +- components/sql/class.sql.conversions.php | 63 ++-- components/sql/class.sql.php | 13 +- components/user/class.user.php | 2 +- 17 files changed, 425 insertions(+), 699 deletions(-) delete mode 100755 components/install/process.php delete mode 100644 components/install/sql/mysql.sql delete mode 100644 components/install/sql/pgsql.sql delete mode 100644 components/install/sql/sqlite.sql diff --git a/components/active/class.active.php b/components/active/class.active.php index b515cae..77dcd11 100755 --- a/components/active/class.active.php +++ b/components/active/class.active.php @@ -1,173 +1,194 @@ actives = getJSON('active.php'); - } - - ////////////////////////////////////////////////////////////////// - // List User's Active Files - ////////////////////////////////////////////////////////////////// - - public function ListActive() - { - $active_list = array(); - $tainted = false; - $root = WORKSPACE; - if ($this->actives) { - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username']) && $data['username']==$this->username) { - if ($this->isAbsPath($data['path'])) { - $root = ""; - } else { - $root = $root.'/'; - } - if (file_exists($root.$data['path'])) { - $focused = isset($data['focused']) ? $data['focused'] : false; - $active_list[] = array('path'=>$data['path'], 'focused'=>$focused); - } else { - unset($this->actives[$active]); - $tainted = true; - } - } - } - } - if ($tainted) { - saveJSON('active.php', $this->actives); - } - echo formatJSEND("success", $active_list); - } - - ////////////////////////////////////////////////////////////////// - // Check File - ////////////////////////////////////////////////////////////////// - - public function Check() - { - $cur_users = array(); - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username']) && $data['username']!=$this->username && $data['path']==$this->path) { - $cur_users[] = $data['username']; - } - } - if (count($cur_users)!=0) { - //echo formatJSEND("error", "Warning: File ".substr($this->path, strrpos($this->path, "/")+1)." Currently Opened By: " . implode(", ", $cur_users)); - } else { - echo formatJSEND("success"); - } - } - - ////////////////////////////////////////////////////////////////// - // Add File - ////////////////////////////////////////////////////////////////// - - public function Add() - { - $process_add = true; - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username']) && $data['username']==$this->username && $data['path']==$this->path) { - $process_add = false; - } - } - if ($process_add) { - $this->actives[] = array("username"=>$this->username,"path"=>$this->path); - saveJSON('active.php', $this->actives); - echo formatJSEND("success"); - } - } - - ////////////////////////////////////////////////////////////////// - // Rename File - ////////////////////////////////////////////////////////////////// - - public function Rename() - { - $revised_actives = array(); - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username'])) { - $revised_actives[] = array("username"=>$data['username'],"path"=>str_replace($this->path, $this->new_path, $data['path'])); - } - } - saveJSON('active.php', $revised_actives); - echo formatJSEND("success"); - } - - ////////////////////////////////////////////////////////////////// - // Remove File - ////////////////////////////////////////////////////////////////// - - public function Remove() - { - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username']) && $this->username==$data['username'] && $this->path==$data['path']) { - unset($this->actives[$active]); - } - } - saveJSON('active.php', $this->actives); - echo formatJSEND("success"); - } - - ////////////////////////////////////////////////////////////////// - // Remove All Files - ////////////////////////////////////////////////////////////////// - - public function RemoveAll() - { - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username']) && $this->username==$data['username']) { - unset($this->actives[$active]); - } - } - saveJSON('active.php', $this->actives); - echo formatJSEND("success"); - } - - ////////////////////////////////////////////////////////////////// - // Mark File As Focused - // All other files will be marked as non-focused. - ////////////////////////////////////////////////////////////////// - - public function MarkFileAsFocused() - { - foreach ($this->actives as $active => $data) { - if (is_array($data) && isset($data['username']) && $this->username==$data['username']) { - $this->actives[$active]['focused']=false; - if ($this->path==$data['path']) { - $this->actives[$active]['focused']=true; - } - } - } - saveJSON('active.php', $this->actives); - echo formatJSEND("success"); - } +class Active extends Common { + + ////////////////////////////////////////////////////////////////// + // PROPERTIES + ////////////////////////////////////////////////////////////////// + + public $username = ""; + public $path = ""; + public $new_path = ""; + + ////////////////////////////////////////////////////////////////// + // METHODS + ////////////////////////////////////////////////////////////////// + + // -----------------------------||----------------------------- // + + ////////////////////////////////////////////////////////////////// + // Construct + ////////////////////////////////////////////////////////////////// + + public function __construct() { + } + + ////////////////////////////////////////////////////////////////// + // List User's Active Files + ////////////////////////////////////////////////////////////////// + + public function ListActive() { + + global $sql; + $query = "SELECT path,focused FROM active WHERE username=?"; + $bind_variables = array( $this->username ); + $result = $sql->query( $query, $bind_variables, array() ); + $tainted = false; + $root = WORKSPACE; + $active_list = $result; + + if( ! empty( $return ) ) { + + foreach ( $result as $id => $data ) { + + if ( $this->isAbsPath( $data['path'] ) ) { + + $root = ""; + } else { + + $root = $root.'/'; + } + + if ( ! file_exists( $root . $data['path'] ) ) { + + $tainted = true; + unset( $active_list[$id] ); + } + } + } + + if( $tainted ) { + + $this->update_active( $active_list ); + } + + echo formatJSEND( "success", $active_list ); + } + + ////////////////////////////////////////////////////////////////// + // Check File + ////////////////////////////////////////////////////////////////// + + public function Check() { + + global $sql; + $query = "SELECT username FROM active WHERE path=?"; + $bind_variables = array( $this->path ); + $result = $sql->query( $query, $bind_variables, array() ); + $tainted = false; + $user = false; + $users = array(); + $root = WORKSPACE; + + foreach( $result as $id => $data ) { + + array_push( $users, $data["username"] ); + if( $data["username"] == $this->username ) { + + $user = true; + } + } + + if ( ( count( $result ) == 1 && ! $user ) || count( $result ) > 1 ) { + + echo formatJSEND( "warning", "Warning: File " . substr( $this->path, strrpos( $this->path, "/" ) +1 ) . " Currently Opened By: " . implode( ", ", $users ) ); + } else { + + echo formatJSEND("success"); + } + } + + ////////////////////////////////////////////////////////////////// + // Add File + ////////////////////////////////////////////////////////////////// + + public function Add() { + + global $sql; + $query = "INSERT INTO active( username, path, focused ) VALUES ( ?, ?, ? );"; + $bind_variables = array( $this->username, $this->path, false ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { + + echo formatJSEND( "success" ); + } + } + + ////////////////////////////////////////////////////////////////// + // Rename File + ////////////////////////////////////////////////////////////////// + + public function Rename() { + + global $sql; + $query = "UPDATE active SET path=? WHERE path=?;"; + $bind_variables = array( $this->new_path, $this->path ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { + + echo formatJSEND( "success" ); + } + } + + ////////////////////////////////////////////////////////////////// + // Remove File + ////////////////////////////////////////////////////////////////// + + public function Remove() { + + global $sql; + $query = "DELETE FROM active WHERE path=? AND username=?;"; + $bind_variables = array( $this->path, $this->username ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { + + echo formatJSEND( "success" ); + } + } + + ////////////////////////////////////////////////////////////////// + // Remove All Files + ////////////////////////////////////////////////////////////////// + + public function RemoveAll() { + + global $sql; + $query = "DELETE FROM active WHERE username=?;"; + $bind_variables = array( $this->username ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { + + echo formatJSEND( "success" ); + } + } + + ////////////////////////////////////////////////////////////////// + // Mark File As Focused + // All other files will be marked as non-focused. + ////////////////////////////////////////////////////////////////// + + public function MarkFileAsFocused() { + + global $sql; + $query = "UPDATE active SET focused=? WHERE username=?;UPDATE active SET focused=? WHERE path=? AND username=?;"; + $bind_variables = array( false, $this->username, true, $this->path, $this->username ); + $return = $sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $return > 0 ) { + + echo formatJSEND( "success" ); + } + } } diff --git a/components/active/init.js b/components/active/init.js index b3b138b..b721657 100755 --- a/components/active/init.js +++ b/components/active/init.js @@ -669,9 +669,8 @@ var newSession = this.sessions[newPath]; // Change Editor Mode - var ext = codiad.filemanager.getExtension(newPath); - var mode = codiad.editor.selectMode(ext); - + var mode = codiad.editor.selectMode(newPath); + // handle async mode change var fn = function() { codiad.editor.setModeDisplay(newSession); diff --git a/components/autosave/init.js b/components/autosave/init.js index 8133009..e3889f3 100755 --- a/components/autosave/init.js +++ b/components/autosave/init.js @@ -99,7 +99,17 @@ amplify.subscribe( 'active.onClose', function( path ) { let _this = codiad.auto_save; - _this.editor.removeEventListener( "change", _this.change ); + try { + + _this.editor.removeEventListener( "change", _this.change ); + } catch( e ) { + + /** + * If the listener is not currently on file and we + * try to close it, the program will throw an exception and + * stop you from closing the file + */ + } }); /* Subscribe to know when a file become active. */ diff --git a/components/editor/init.js b/components/editor/init.js index fe1427b..681a421 100755 --- a/components/editor/init.js +++ b/components/editor/init.js @@ -321,18 +321,18 @@ // ////////////////////////////////////////////////////////////////// - getSettings: function() { + getSettings: async function() { - var boolVal = null; - var _this = this; - var options = [ + let boolVal = null; + let _this = this; + let options = [ 'editor.fontSize', 'editor.overScroll', 'editor.printMarginColumn', 'editor.tabSize', 'editor.theme', ]; - var bool_options = [ + let bool_options = [ 'editor.autocomplete', 'settings.autosave', 'editor.printMargin', @@ -345,9 +345,11 @@ 'editor.persistentModal', ]; - $.each( options, async function( idx, key ) { + let user_settings = await codiad.settings.get_options(); + + $.each( options, function( idx, key ) { - let localValue = await codiad.settings.get_option( 'codiad.' + key ); + let localValue = user_settings['codiad.' + key]; if ( localValue != null ) { _this.settings[key.split('.').pop()] = localValue; @@ -356,7 +358,7 @@ $.each( bool_options, async function(idx, key) { - let localValue = await codiad.settings.get_option( 'codiad.' + key ); + let localValue = user_settings['codiad.' + key]; if ( localValue != null ) { _this.settings[key.split('.').pop()] = (localValue == 'true'); diff --git a/components/install/install.php b/components/install/install.php index 7388155..df94187 100644 --- a/components/install/install.php +++ b/components/install/install.php @@ -1,5 +1,12 @@ active = $path . "/data/active.php"; - $this->config = $path . "/config.php"; - $this->projects = $path . "/data/projects.php"; - $this->path = $path; - $this->sessions = $path . "/data/sessions"; - $this->users = $path . "/data/users.php"; - $this->rel = $rel; - $this->workspace = $path . "/workspace"; - $this->db_types = sql::db_types; - - $this->check(); - - require_once( "../sql/class.sql.php" ); - $this->sql = new sql(); - $this->install(); + if( isset( $_POST["path"] ) ) { + + $path = $_POST['path']; + $rel = str_replace( '/components/install/install.php', '', $_SERVER['REQUEST_URI'] ); + + $this->active = $path . "/data/active.php"; + $this->config = $path . "/config.php"; + $this->projects = $path . "/data/projects.php"; + $this->path = $path; + $this->sessions = $path . "/data/sessions"; + $this->users = $path . "/data/users.php"; + $this->rel = $rel; + $this->workspace = $path . "/workspace"; + $this->db_types = sql::DB_TYPES; + $this->project_name = $_POST["project_name"]; + $this->project_path = $this->clean_path( $_POST["project_path"] ); + $this->username = $this->clean_username( $_POST["username"] ); + $this->password = $this->encrypt_password( $_POST["password"] ); + + $this->check(); + $this->sql = new sql(); + $this->install(); + exit; + } } function check() { @@ -51,7 +64,12 @@ class Install { if( ! in_array( DBTYPE, $this->db_types ) ) { - $this->JSEND( "Invalid database. Please select one of the following: " . implode( ", ", $db_types ), addslashes( json_encode( array( $dbtype, $db_types ) ) ) ); + $this->JSEND( "Invalid database. Please select one of the following: " . implode( ", ", $db_types ), json_encode( array( $dbtype, $db_types ) ) ); + } + + if( ! is_dir( $this->sessions ) ) { + + mkdir( $this->sessions, 00755 ); } } @@ -134,20 +152,20 @@ define("WSURL", BASE_URL . "/workspace"); // Marketplace //define("MARKETURL", "http://market.codiad.com/json"); '; - saveFile( $config, $config_data ); + $this->save_file( $this->config, $config_data ); echo( "success" ); } function create_project() { - $project_path = $this->clean_path( $project_path ); + $project_path = $this->project_path; if ( ! $this->is_abs_path( $project_path ) ) { $project_path = str_replace( " ", "_", preg_replace( '/[^\w-\.]/', '', $project_path ) ); - if( ! is_dir( $workspace . "/" . $project_path ) ) { + if( ! is_dir( $this->workspace . "/" . $project_path ) ) { - mkdir( $workspace . "/" . $project_path ); + mkdir( $this->workspace . "/" . $project_path ); } } else { @@ -171,11 +189,12 @@ define("WSURL", BASE_URL . "/workspace"); } $bind_variables = array( - $project_name, + $this->project_name, $project_path, - $username + $this->username ); $query = "INSERT INTO projects(name, path, owner) VALUES (?,?,?);"; + $connection = $this->sql->connect(); $statement = $connection->prepare( $query ); $statement->execute( $bind_variables ); $error = $statement->errorInfo(); @@ -190,6 +209,18 @@ define("WSURL", BASE_URL . "/workspace"); $this->sql->create_tables( array( + "active" => array( + "fields" => array( + "username" => "string", + "path" => "text", + "focused" => "string" + ), + "attributes" => array( + "username" => array( "not null", "unique" ), + "path" => array( "not null", "unique" ), + "focused" => array( "not null" ), + ) + ), "options" => array( "fields" => array( "id" => "int", @@ -216,7 +247,7 @@ define("WSURL", BASE_URL . "/workspace"); "name" => array( "not null" ), "path" => array( "not null", "unique" ), "owner" => array( "not null", "unique" ), - "access" => array( "not null" ), + "access" => array(), ) ), "users" => array( @@ -262,15 +293,16 @@ define("WSURL", BASE_URL . "/workspace"); $bind_variables = array( "", "", - $username, - $password, + $this->username, + $this->password, "", - $project_path, + $this->project_path, "admin", "", "" ); $query = "INSERT INTO users(first_name, last_name, username, password, email, project, access, groups, token) VALUES (?,?,?,?,?,?,?,?,?)"; + $connection = $this->sql->connect(); $statement = $connection->prepare( $query ); $statement->execute( $bind_variables ); $error = $statement->errorInfo(); @@ -279,6 +311,13 @@ define("WSURL", BASE_URL . "/workspace"); die( '{"message":"Could not create user in database.","error":"' . addslashes(json_encode( $error )) .'"}' ); } + + $this->set_default_options(); + } + + function encrypt_password( $string ) { + + return sha1( md5( $string ) ); } function is_abs_path( $path ) { @@ -309,6 +348,7 @@ define("WSURL", BASE_URL . "/workspace"); $this->create_tables(); $this->create_project(); $this->create_user(); + //exit( "stop" ); $this->create_config(); } @@ -325,6 +365,37 @@ define("WSURL", BASE_URL . "/workspace"); exit( json_encode( $message ) ); } + function save_file( $file, $data ) { + + $write = fopen( $file, 'w' ) or die( '{"message": "can\'t open file"}' ); + fwrite( $write, $data ); + fclose( $write ); + } + + public function set_default_options() { + + foreach( Settings::DEFAULT_OPTIONS as $id => $option ) { + + $query = "INSERT INTO user_options ( name, username, value ) VALUES ( ?, ?, ? );"; + $bind_variables = array( + $option["name"], + $this->username, + $option["value"], + ); + $result = $this->sql->query( $query, $bind_variables, 0, "rowCount" ); + + if( $result == 0 ) { + + $query = "UPDATE user_options SET value=? WHERE name=? AND username=?;"; + $bind_variables = array( + $option["value"], + $option["name"], + $this->username, + ); + $result = $this->sql->query( $query, $bind_variables, 0, "rowCount" ); + } + } + } } $Install = new Install(); diff --git a/components/install/process.php b/components/install/process.php deleted file mode 100755 index 5eaa186..0000000 --- a/components/install/process.php +++ /dev/null @@ -1,295 +0,0 @@ -"; - saveFile( $file, $data ); -} - -function encryptPassword( $p ) { - - return sha1( md5( $p ) ); -} - -function cleanUsername( $username ) { - - return preg_replace( '#[^A-Za-z0-9' . preg_quote( '-_@. ' ). ']#', '', $username ); -} - -function isAbsPath( $path ) { - - return $path[0] === '/'; -} - -function cleanPath( $path ) { - - // prevent Poison Null Byte injections - $path = str_replace( chr( 0 ), '', $path ); - - // prevent go out of the workspace - while ( strpos( $path, '../' ) !== false ) { - - $path = str_replace( '../', '', $path ); - } - return $path; -} - -////////////////////////////////////////////////////////////////////// -// Verify no overwrites -////////////////////////////////////////////////////////////////////// - -if ( ! ( defined( 'DBHOST' ) && defined( 'DBNAME' ) && defined( 'DBUSER' ) && defined( 'DBPASS' ) && defined( 'DBTYPE' ) ) ) { - - ////////////////////////////////////////////////////////////////// - // Get POST responses - ////////////////////////////////////////////////////////////////// - - $username = cleanUsername( $_POST['username'] ); - $password = encryptPassword( $_POST['password'] ); - $project_name = $_POST['project_name']; - if ( isset( $_POST['project_path'] ) ) { - - $project_path = $_POST['project_path']; - } else { - - $project_path = $project_name; - } - $timezone = $_POST['timezone']; - - $dbtype = $_POST['dbtype']; - $dbhost = $_POST['dbhost']; - $dbname = $_POST['dbname']; - $dbuser = $_POST['dbuser']; - $dbpass = $_POST['dbpass']; - - //Valid databases Codiad is able to use - $db_types = [ - 'mysql', - 'pgsql', - //'sqlite', - ]; - - //Is selected database type valid? - if( ! in_array( $dbtype, $db_types ) ) { - - die( '{"message": "Invalid database. Please select one of the following: ' . implode( ", ", $db_types ) . '.", "error": "' . addslashes(json_encode( array( $dbtype, $db_types ) ) ) . '"}' ); - } - - try { - - $connection = new PDO( "{$dbtype}:host={$dbhost};dbname={$dbname}", $dbuser, $dbpass ); - } catch( PDOException $e ) { - - die( '{"message":"Could not connect to database.","error":"' . addslashes( json_encode( $e->getMessage() ) ) .'"}' ); - } - $bind_vars = array(); - $bind = ""; - $database_sql_fullpath = $path . '/components/install/sql/' . $dbtype . '.sql'; - if( ! is_file( $database_sql_fullpath ) ) { - - die( '{"message":"Could not find the sql script for the database type: ' . $dbtype . '","error":"' . addslashes( json_encode( array( "path" => $database_sql_fullpath, "dbtype" => $dbtype ) ) ) .'"}' ); - } - $sql = file_get_contents( $database_sql_fullpath ); - - try { - - //Create the database - $result = $connection->exec( $sql ); - } catch( PDOException $e ) { - - die( '{"message":"Could not create initial tables in database.","error":"' . addslashes( json_encode( $e->getMessage() ) ) .'"}' ); - } - - $error = $connection->errorInfo(); - if( ! $error[0] == "00000" ) { - - die( '{"message":"Could not create initial tables in database.","error":"' . addslashes( json_encode( $error ) ) .'"}' ); - } - - ////////////////////////////////////////////////////////////////// - // Create Projects files - ////////////////////////////////////////////////////////////////// - - $project_path = cleanPath( $project_path ); - - if ( ! isAbsPath( $project_path ) ) { - - $project_path = str_replace( " ", "_", preg_replace( '/[^\w-\.]/', '', $project_path ) ); - if( ! is_dir( $workspace . "/" . $project_path ) ) { - - mkdir( $workspace . "/" . $project_path ); - } - } else { - - $project_path = cleanPath( $project_path ); - if ( substr( $project_path, -1 ) == '/' ) { - - $project_path = substr( $project_path, 0, strlen( $project_path ) - 1 ); - } - if ( ! file_exists( $project_path ) ) { - - if ( ! mkdir( $project_path . '/', 0755, true ) ) { - - die( '{"message": "Unable to create Absolute Path"}' ); - } - } else { - - if ( ! is_writable( $project_path ) || ! is_readable( $project_path ) ) { - - die( '{"message": "No Read/Write Permission"}' ); - } - } - } - - $bind_variables = array( - $project_name, - $project_path, - $username - ); - $query = "INSERT INTO projects(name, path, owner) VALUES (?,?,?);"; - $statement = $connection->prepare( $query ); - $statement->execute( $bind_variables ); - $error = $statement->errorInfo(); - - if( ! $error[0] == "00000" ) { - - die( '{"message":"Could not create project in database.","error":"' . addslashes(json_encode( $error )) .'"}' ); - } - - $bind_variables = array( - "", - "", - $username, - $password, - "", - $project_path, - "admin", - "", - "" - ); - $query = "INSERT INTO users(first_name, last_name, username, password, email, project, access, groups, token) VALUES (?,?,?,?,?,?,?,?,?)"; - $statement = $connection->prepare( $query ); - $statement->execute( $bind_variables ); - $error = $statement->errorInfo(); - - if( ! $error[0] == "00000" ) { - - die( '{"message":"Could not create user in database.","error":"' . addslashes(json_encode( $error )) .'"}' ); - } - - - /** - * Create sessions path. - */ - - if ( ! is_dir( $sessions ) ) { - - mkdir( $sessions, 00755 ); - } - - ////////////////////////////////////////////////////////////////// - // Create Active file - ////////////////////////////////////////////////////////////////// - - saveJSON( $active, array( '' ) ); - - ////////////////////////////////////////////////////////////////// - // Create Config - ////////////////////////////////////////////////////////////////// - - - $config_data = '