diff --git a/pandora_console/extensions/update_manager/lang/language_en.php b/pandora_console/extensions/update_manager/lang/language_en.php new file mode 100644 index 0000000000..a171281bf0 --- /dev/null +++ b/pandora_console/extensions/update_manager/lang/language_en.php @@ -0,0 +1,7 @@ + diff --git a/pandora_console/extensions/update_manager/lib/libupdate_manager.php b/pandora_console/extensions/update_manager/lib/libupdate_manager.php new file mode 100644 index 0000000000..b120f5bb99 --- /dev/null +++ b/pandora_console/extensions/update_manager/lib/libupdate_manager.php @@ -0,0 +1,521 @@ +PEAR::DB not found. Please install it with:
pear install DB

'); +error_reporting ($prev_level); +unset ($prev_level); + +require_once ('libupdate_manager_utils.php'); +require_once ('libupdate_manager_updates.php'); +require_once ('libupdate_manager_components.php'); +require_once ('libupdate_manager_client.php'); + +function um_db_load_settings () { + global $db; + + $result =& $db->query ('SELECT * FROM tupdate_settings'); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $settings = new stdClass (); + while ($result->fetchInto ($setting)) { + $key = $setting->key; + $settings->$key = $setting->value; + } + + return $settings; +} + +function um_db_update_setting ($key, $value = '') { + global $db; + + $values = array ($value, $key); + + $sql =& $db->prepare ('UPDATE tupdate_settings SET value = ? WHERE `key` = ?'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_get_latest_public_package ($id_package = '0') { + global $db; + + $values = array ('public', $id_package); + $sql =& $db->prepare ('SELECT * FROM tupdate_package WHERE status = ? AND id > ? ORDER BY id DESC LIMIT 1'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + $result->fetchInto ($package); + + return $package; +} + +function um_db_get_latest_development_package ($id_package = '0') { + global $db; + + $values = array ('development', $id_package); + $sql =& $db->prepare ('SELECT * FROM tupdate_package WHERE status = ? AND id > ? ORDER BY id DESC LIMIT 1'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + $result->fetchInto ($package); + + return $package; +} + +function um_db_get_next_package ($id_package = '0', $development = false) { + global $db; + + $values = array ('public', $id_package); + $sql =& $db->prepare ('SELECT * FROM tupdate_package WHERE status = ? AND id > ? ORDER BY id ASC LIMIT 1'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + $result->fetchInto ($package); + + if (! $package && $development) { + $values = array ('development', $id_package); + $sql =& $db->prepare ('SELECT * FROM tupdate_package WHERE status = ? AND id > ? ORDER BY id ASC LIMIT 1'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + $result->fetchInto ($package); + } + + return $package; +} + +function um_db_create_package ($description = '') { + global $db; + + $sql =& $db->prepare ('INSERT INTO tupdate_package (description) VALUES (?)'); + $result =& $db->execute ($sql, $description); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_update_package ($id_package, $description = '', $status = 'disabled') { + global $db; + + $values = array ($description, $status, $id_package); + + $sql =& $db->prepare ('UPDATE tupdate_package SET description = ?, status = ? WHERE id = ?'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_delete_package ($id_package) { + global $db; + + $package = um_db_get_package ($id_package); + if ($package->status != 'development') { + echo 'Error: '.'Only packages in development state can be deleted'; + return false; + } + + $sql =& $db->prepare ('DELETE FROM tupdate_package WHERE id = ?'); + $result =& $db->execute ($sql, $id_package); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_get_package ($id_package) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate_package WHERE id = ? LIMIT 1'); + $result =& $db->execute ($sql, $id_package); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($package); + + return $package; +} + +function um_db_get_all_packages () { + global $db; + + $result =& $db->query ('SELECT * FROM tupdate_package'); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return array (); + } + $packages = array (); + while ($result->fetchInto ($package)) { + $packages[$package->id] = $package; + } + + return $packages; +} + +function um_db_get_package_updates ($id_package) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate WHERE id_update_package = ?'); + $result =& $db->execute ($sql, $id_package); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $updates = array (); + while ($result->fetchInto ($update)) { + $updates[$update->id] = $update; + } + + return $updates; +} + +function um_db_create_package_log ($id_package, $id_auth, $ip_address = '') { + global $db; + + $values = array ($id_package, $id_auth, $ip_address); + $sql =& $db->prepare ('INSERT INTO tupdate_package_log (id_update_package, id_auth, ip_address) VALUES (?, ?, ?)'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + return false; + } + return true; +} + +function um_db_create_component ($type, $name, $path = '') { + global $db; + + $values = array ($type, $name, $path); + $sql =& $db->prepare ('INSERT INTO tupdate_component (type, name, path) VALUES (?, ?, ?)'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + return true; +} + +function um_db_update_component ($name, $path = '') { + global $db; + + $values = array ($path, $name); + + $sql =& $db->prepare ('UPDATE tupdate_component SET path = ? WHERE name = ?'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_delete_component ($name) { + global $db; + + $sql =& $db->prepare ('DELETE FROM tupdate_component WHERE name = ?'); + $result =& $db->execute ($sql, $name); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_get_component ($name) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate_component WHERE name = ? LIMIT 1'); + $result =& $db->execute ($sql, $name); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($component); + + return $component; +} + +function um_db_get_all_components ($type = '') { + global $db; + + if ($type != '') { + $sql =& $db->prepare ('SELECT * FROM tupdate_component WHERE type = ?'); + $result =& $db->execute ($sql, $type); + } else { + $result =& $db->query ('SELECT * FROM tupdate_component'); + } + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return array (); + } + $components = array (); + while ($result->fetchInto ($component)) { + $components[$component->name] = $component; + } + + return $components; +} + +function um_db_create_component_db ($table_name, $field_name, $order, $component_name) { + global $db; + + $values = array ($table_name, $field_name, $order, $component_name); + $sql =& $db->prepare ('INSERT INTO tupdate_component_db (table_name, field_name, `order`, component) VALUES (?, ?, ?, ?)'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_update_component_db ($id, $table_name = '', $field_name = '', $order = '') { + global $db; + + $values = array ($table_name, $field_name, $order, $id); + $sql =& $db->prepare ('UPDATE tupdate_component_db SET table_name = ?, field_name = ?, `order` = ? WHERE id = ?'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_delete_component_db ($id) { + global $db; + + $sql =& $db->prepare ('DELETE FROM tupdate_component_db WHERE id = ?'); + $result =& $db->execute ($sql, $id); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_get_component_db ($id_component_db) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate_component_db WHERE id = ? LIMIT 1'); + $result =& $db->execute ($sql, $id_component_db); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($component); + + return $component; +} + +function um_db_get_database_components ($component_name) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate_component_db WHERE component = ? ORDER BY `order` ASC'); + $result =& $db->execute ($sql, $component_name); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $components = array (); + while ($result->fetchInto ($component)) { + $components[$component->id] = $component; + } + + return $components; +} + +function um_db_create_auth ($client_key, $subscription_limit, $description = '', $developer = false) { + global $db; + + if (! is_numeric ($subscription_limit)) { + echo 'Error: Subscription must be numeric
'; + return false; + } + $values = array ($client_key, $subscription_limit, $description, $developer); + $sql =& $db->prepare ('INSERT INTO tupdate_auth (client_key, subscription_limit, description, developer) VALUES (?, ?, ?, ?)'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + return true; +} + +function um_db_update_auth ($id_auth, $client_key, $subscription_limit, $description = '', $developer = false) { + global $db; + + if (! is_numeric ($subscription_limit)) { + echo 'Error: Subscription must be numeric
'; + return false; + } + $values = array ($client_key, $subscription_limit, $description, + $developer, $id_auth); + $sql =& $db->prepare ('UPDATE tupdate_auth SET client_key = ?, subscription_limit = ?, description = ?, developer = ? WHERE id = ?'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_delete_auth ($id_auth) { + global $db; + + $sql =& $db->prepare ('DELETE FROM tupdate_auth WHERE id = ?'); + $result =& $db->execute ($sql, $id_auth); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + + return true; +} + +function um_db_get_auth ($id_auth) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate_auth WHERE id = ? LIMIT 1'); + $result =& $db->execute ($sql, $id_auth); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($auth); + + return $auth; +} + +function um_db_get_all_auths () { + global $db; + + $result =& $db->query ('SELECT * FROM tupdate_auth'); + + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return array (); + } + $auths = array (); + while ($result->fetchInto ($auth)) { + $auths[$auth->id] = $auth; + } + + return $auths; +} + +function um_db_check_auth ($client_key, $subscription_limit) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate_auth WHERE client_key = ? LIMIT 1'); + $result =& $db->execute ($sql, $client_key); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + $result->fetchInto ($auth); + if (! $auth) + return false; + + if ($auth->developer == 1) + return $auth->id; + + if ($auth->subscription_limit >= $subscription_limit) + return $auth->id; + return false; +} + +function um_db_is_auth_developer ($id_auth) { + global $db; + + $developer =& $db->getOne ('SELECT developer FROM tupdate_auth WHERE id = ? LIMIT 1', $id_auth); + if (PEAR::isError ($developer)) { + echo 'Error: '.$developer->getMessage ().'
'; + return false; + } + return (bool) $developer; +} + +function um_db_connect ($backend = 'mysql', $host = '', $user = '', $password = '', $db_name = '') { + static $db = NULL; + + if ($db) + return $db; + + $dsn = $backend.'://'.$user.':'.$password.'@'.$host.'/'.$db_name; + $db =& DB::Connect ($dsn, array ()); + if (PEAR::isError ($db)) { + echo 'Error: '.$db->getMessage ().'
'; + die; + } + $db->setFetchMode (DB_FETCHMODE_OBJECT); + + return $db; +} + +function um_component_db_connect () { + $settings = um_db_load_settings (); + + $dsn = 'mysql://'.$settings->dbuser.':'.$settings->dbpass.'@'.$settings->dbhost.'/'.$settings->dbname; + $db =& DB::Connect ($dsn, array ()); + if (PEAR::isError ($db)) { + return false; + } + $db->setFetchMode (DB_FETCHMODE_ORDERED); + + return $db; +} + +function um_get_package_status () { + $status = array (); + + $status['development'] = 'Development'; + $status['testing'] = 'Testing'; + $status['public'] = 'Public'; + $status['disabled'] = 'Disabled'; + + return $status; +} + +function um_get_component_types () { + $types = array (); + + $types['database'] = 'Database'; + $types['directory'] = 'Code / binary directory'; + + return $types; +} +?> diff --git a/pandora_console/extensions/update_manager/lib/libupdate_manager_client.php b/pandora_console/extensions/update_manager/lib/libupdate_manager_client.php new file mode 100644 index 0000000000..68ecd32e81 --- /dev/null +++ b/pandora_console/extensions/update_manager/lib/libupdate_manager_client.php @@ -0,0 +1,333 @@ +PEAR::XML_RPC not found. Please install it with:
pear install XML_RPC

'); +error_reporting ($prev_level); +unset ($prev_level); + +define ('XMLRPC_DEBUG', 0); + +function um_xml_rpc_client_call ($server_host, $server_path, $server_port, $function, $parameters) { + $msg = new XML_RPC_Message ($function, $parameters); + $client = new XML_RPC_Client ($server_path, $server_host, $server_port); + if (defined ('XMLRPC_DEBUG')) + $client->setDebug (XMLRPC_DEBUG); + $result = $client->send ($msg); + + if (! $result) { + trigger_error ('Open Update Manager Server comunication error. '.$client->errstr); + return false; + } + if ($result->faultCode ()) { + trigger_error ('Open Update Manager XML-RPC error. '.$result->faultString ()); + return false; + } + + return $result; +} + +function um_xml_rpc_unpack_update ($update_xml_rpc) { + if ($update_xml_rpc->kindOf () != 'struct') { + return false; + } + + $update = new stdClass (); + $value = $update_xml_rpc->structeach (); + while ($value) { + $update->$value['key'] = $value[1]->scalarval (); + $value = $update_xml_rpc->structeach (); + } + + return $update; +} + +function um_xml_rpc_unpack_package ($package_xml_rpc) { + if ($package_xml_rpc->kindOf () != 'struct') { + return false; + } + + $package = new stdClass (); + $value = $package_xml_rpc->structeach (); + while ($value) { + $package->$value['key'] = $value[1]->scalarval (); + $value = $package_xml_rpc->structeach (); + } + + if (! isset ($package->updates)) + return $package; + + $package->updates = array (); + $updates = $package_xml_rpc->structmem ('updates'); + $size = $updates->arraysize (); + for ($i = 0; $i < $size; $i++) { + $update = um_xml_rpc_unpack_update ($updates->arraymem ($i)); + $update->id_update_package = $package->id; + array_push ($package->updates, $update); + } + + return $package; +} + +function um_client_check_latest_update ($settings, $user_key) { + $params = array (new XML_RPC_Value ($settings->customer_key, 'string'), + new XML_RPC_Value ($user_key, 'string'), + new XML_RPC_Value ($settings->current_update, 'int')); + $result = um_xml_rpc_client_call ($settings->update_server_host, + $settings->update_server_path, + $settings->update_server_port, + 'get_latest_package', $params); + + if ($result === false) { + return false; + } + + $value = $result->value (); + if ($value->kindOf () == 'scalar') { + /* No new updates */ + return $value->scalarval (); + } + + $package = um_xml_rpc_unpack_package ($value); + + return $package; +} + +function um_client_get_package ($settings, $user_key) { + $params = array (new XML_RPC_Value ($settings->customer_key, 'string'), + new XML_RPC_Value ($user_key, 'string'), + new XML_RPC_Value ($settings->current_update, 'int')); + $result = um_xml_rpc_client_call ($settings->update_server_host, + $settings->update_server_path, + $settings->update_server_port, + 'get_next_package', $params); + + if ($result === false) + return false; + + $value = $result->value (); + if ($value->kindOf () == 'scalar') { + /* No new updates */ + return (bool) $value->scalarval (); + } + + $package = um_xml_rpc_unpack_package ($value); + + return $package; +} + +function um_client_db_save_package ($package) { + global $db; + + $fields = array ('id' => $package->id, + 'description' => $package->description); + $replace = array (); + for ($i = 0; $i < sizeof ($fields); $i++) { + $replace[] = '?'; + } + + $sql =& $db->prepare ('INSERT INTO tupdate_package ('.implode(',', array_keys (&$fields)).') VALUES ('.implode(',', &$replace).')'); + $result =& $db->execute ($sql, $fields); + if (PEAR::isError ($result)) { + return false; + } + return true; +} + +function um_client_db_save_update ($update) { + global $db; + + $fields = array_keys (get_object_vars (&$update)); + $values = array_values (get_object_vars (&$update)); + $replace = array (); + for ($i = 0; $i < sizeof ($values); $i++) { + $replace[] = '?'; + } + + $sql =& $db->prepare ('INSERT INTO tupdate ('.implode(',', &$fields).') VALUES ('.implode(',', &$replace).')'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + return false; + } + return true; +} + +function um_client_apply_update_file ($update, $destiny_filename, $force = false) { + if (! is_writable ($destiny_filename)) { + return false; + } + + if (file_exists ($destiny_filename)) { + $checksum = md5_file ($destiny_filename); + if (! $force &&$update->previous_checksum != '') { + if ($update->previous_checksum != $checksum) + /* Local changes in the file. Don't update */ + return false; + } + $content = file_get_contents ($destiny_filename); + $update->data_rollback = convert_uuencode ($content); + $update->previous_checksum = $checksum; + } + $result = file_put_contents ($destiny_filename, convert_uudecode ($update->data)); + + if ($result === false) { + return false; + } + return true; +} + +function um_client_apply_update_database ($update, $db) { + if ($update->type == 'db_data') { + $values = array ($update->db_table, + $update->db_field, + $update->db_field_value); + $exists =& $db->getOne ('SELECT COUNT(*) FROM `!` WHERE ? = ?', $values); + if (PEAR::isError ($exists)) { + return false; + } + /* If it exists, it failed. */ + if ($exists) + return false; + } + + $result =& $db->query ($update->data); + if (PEAR::isError ($result)) { + echo $result->getMessage (); + return false; + } + return true; +} + +function um_client_apply_update ($update, $settings, $db, $force = false) { + if ($update->type == 'code') { + $filename = realpath ($settings->updating_code_path.'/'.$update->filename); + $success = um_client_apply_update_file (&$update, &$filename, $force); + } else if ($update->type == 'binary') { + $filename = realpath ($settings->updating_binary_path.'/'.$update->filename); + $success = um_client_apply_update_file (&$update, &$filename); + } else if ($update->type == 'db_data' || $update->type == 'db_schema') { + $success = um_client_apply_update_database (&$update, &$db); + } else { + return false; + } + + if (! $success) + return false; + return true; +} + +function um_client_rollback_update_file ($update, $destiny_filename) { + /* If there's no data rollback, we suppose it's a new file, so it should + not be a problem. In any case, it's better than deleting the file. */ + if (! isset ($update->data_rollback)) + return true; + + $result = file_put_contents ($destiny_filename, convert_uudecode ($update->data_rollback)); + + if ($result === false) + return false; + return true; +} + +function um_client_rollback_update ($update, $settings, $db) { + if ($update->type == 'code') { + $filename = realpath ($settings->updating_code_path.'/'.$update->filename); + $success = um_client_rollback_update_file (&$update, &$filename); + } else if ($update->type == 'binary') { + $filename = realpath ($settings->updating_binary_path.'/'.$update->filename); + $success = um_client_rollback_update_file (&$update, &$filename); + } else if ($update->type == 'db_data' || $update->type == 'db_schema') { + $db->rollback (); + $success = true; + } else { + return false; + } + + return $success; +} + +function um_client_print_update ($update, $settings) { + echo 'Update #'.$update->id; + echo ''; +} + +function um_client_upgrade_to_package ($package, $settings, $force = false) { + $applied_updates = array (); + $rollback = false; + + $db = um_client_db_connect (&$settings); + if ($db === false) + return false; + foreach ($package->updates as $update) { + $success = um_client_apply_update (&$update, &$settings, &$db, $force); + if (! $success) { + echo '

Failed on:
'; + um_client_print_update ($update, $settings); + $rollback = true; + break; + } + array_push ($applied_updates, $update); + } + + if ($rollback) { + foreach ($applied_updates as $update) { + $success = um_client_rollback_update (&$update, &$settings, &$db); + } + return false; + } + $db->commit (); + um_client_db_save_package ($package); + foreach ($package->updates as $update) { + um_client_db_save_update ($update); + } + + um_db_update_setting ('current_update', $package->id); + return true; +} + +function um_client_upgrade_to_latest ($user_key, $force) { + $settings = um_db_load_settings (); + do { + $package = um_client_get_package ($settings, $user_key); + if ($package === false || $package === true) + break; + $success = um_client_upgrade_to_package ($package, $settings, $force); + if (! $success) + break; + + + $settings->current_update = $package->id; + } while (1); + /* Break on error, when there are no more packages on the server (server return true) + or on auth failure (server return false) */ +} + +function um_client_db_connect ($settings = NULL) { + if (! $settings) + $settings = um_db_load_settings (); + + $dsn = 'mysql://'.$settings->dbuser.':'.$settings->dbpass.'@'.$settings->dbhost.'/'.$settings->dbname; + $db =& DB::Connect ($dsn, array ()); + if (PEAR::isError ($db)) { + return false; + } + $db->setFetchMode (DB_FETCHMODE_ASSOC); + $db->autoCommit (false); + + return $db; +} +?> diff --git a/pandora_console/extensions/update_manager/lib/libupdate_manager_components.php b/pandora_console/extensions/update_manager/lib/libupdate_manager_components.php new file mode 100644 index 0000000000..a4e587fd55 --- /dev/null +++ b/pandora_console/extensions/update_manager/lib/libupdate_manager_components.php @@ -0,0 +1,119 @@ +setFetchMode (DB_FETCHMODE_OBJECT); + + $fields = um_component_database_get_table_fields ($component_db->table_name); + $sql =& $db->prepare ('SELECT '.implode (',', $fields).' FROM !'); + $result =& $db->execute ($sql, $component_db->table_name); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $resultdata = array (); + $field = $component_db->field_name; + while ($result->fetchInto ($data)) { + $update = um_update_get_last_from_table_field_value ($component_db->component, + $component_db->id, + $data->$field); + if ($update && $update->db_field_value == $data->$field) + continue; + array_push ($resultdata, $data); + } + + return $resultdata; +} + +function um_component_database_get_all_tables () { + $db = um_component_db_connect (); + + if ($db === false) { + return array (); + } + + $result =& $db->query ('SHOW TABLES'); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return array (); + } + $tables = array (); + while ($result->fetchInto ($table)) { + array_push ($tables, $table[0]); + } + + return $tables; +} + +function um_component_database_get_available_tables ($component_name) { + $all_tables = um_component_database_get_all_tables (); + $components_db = um_db_get_database_components ($component_name); + $defined_tables = array (); + foreach ($components_db as $component_db) { + array_push ($defined_tables, $component_db->table_name); + } + + return array_diff ($all_tables, $defined_tables); +} + +function um_component_database_get_table_fields ($table_name) { + $db = um_component_db_connect (); + + if ($db === false) { + return array (); + } + + $sql =& $db->prepare ('SHOW COLUMNS FROM ! WHERE `Key` \!= "PRI"'); + $result =& $db->execute ($sql, $table_name); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return array (); + } + + $fields = array (); + while ($result->fetchInto ($field)) { + array_push ($fields, $field[0]); + } + return $fields; +} + +function um_component_directory_get_all_files ($component, $binary = false) { + if (! $component || ! isset ($component->path)) { + return array (); + } + + if (! is_dir ($component->path)) { + return array (); + } + + $path = $component->path; + if (substr ($path, -1) != '/') + $path .= "/"; + $files = directory_to_array ($path, + array ('.svn', '.cvs', '.git', '.', '..' ), $binary); + + return $files; +} + +function um_component_directory_get_modified_files ($component, $binary = false) { + $all_files = um_component_directory_get_all_files ($component, $binary); + + $files = array (); + foreach ($all_files as $file) { + $last_update = um_update_get_last_from_filename ($component->name, $file); + if ($last_update) { + $checksum = md5_file (realpath ($component->path.'/'.$file)); + if ($last_update->checksum == $checksum) + continue; + } + + array_push ($files, $file); + } + + return $files; +} +?> diff --git a/pandora_console/extensions/update_manager/lib/libupdate_manager_updates.php b/pandora_console/extensions/update_manager/lib/libupdate_manager_updates.php new file mode 100644 index 0000000000..fd91ed55fd --- /dev/null +++ b/pandora_console/extensions/update_manager/lib/libupdate_manager_updates.php @@ -0,0 +1,154 @@ +prepare ('SELECT * FROM tupdate WHERE component = ? AND filename = ? ORDER BY id DESC LIMIT 1'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($update); + return $update; +} + +function um_update_get_last_from_table_field_value ($component_name, $id_component_db, $field_value) { + global $db; + + $values = array ($component_name, $id_component_db, $field_value); + $sql =& $db->prepare ('SELECT * FROM tupdate WHERE component = ? AND id_component_db = ? AND db_field_value = ? ORDER BY id DESC LIMIT 1'); + $result =& $db->execute ($sql, $values); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($update); + return $update; +} + +function um_db_get_orphan_updates () { + global $db; + + $result =& $db->query ('SELECT * FROM tupdate WHERE id_update_package IS NULL'); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $updates = array (); + while ($result->fetchInto ($update)) { + $updates[$update['id']] = $update; + } + return $updates; +} + +function um_db_get_update ($id_update) { + global $db; + + $sql =& $db->prepare ('SELECT * FROM tupdate WHERE id = ? LIMIT 1'); + $result =& $db->execute ($sql, $id_update); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return NULL; + } + $result->fetchInto ($update); + + return $update; +} + +function um_db_delete_update ($id_update) { + global $db; + + $update = um_db_get_update ($id_update); + $package = um_db_get_package ($update->id_update_package); + if ($package->status != 'development') { + echo 'Error: '.'Only packages in development state can be deleted'; + return false; + } + + $sql =& $db->prepare ('DELETE FROM tupdate WHERE id = ?'); + $result =& $db->execute ($sql, $id_update); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + return true; +} + +function um_db_create_update ($type, $component_name, $id_package, $update, $db_data = NULL) { + global $db; + + if ($id_package == 0) + return false; + $component = um_db_get_component ($component_name); + $values = array ('type' => $type, + 'component' => $component_name, + 'id_update_package' => $id_package); + switch ($type) { + case 'code': + $filepath = realpath ($component->path.'/'.$update->filename); + $values['svn_version'] = um_file_get_svn_revision ($filepath); + case 'binary': + $last_update = um_update_get_last_from_filename ($component_name, $update->filename); + $filepath = realpath ($component->path.'/'.$update->filename); + $values['checksum'] = md5_file ($filepath); + if ($last_update && $last_update->checksum == $values['checksum']) { + return false; + } + $values['filename'] = $update->filename; + $values['data'] = um_file_uuencode ($filepath); + if ($last_update && $last_update->checksum != '') + $values['previous_checksum'] = $last_update->checksum; + + break; + case 'db_data': + if ($db_data === NULL) + return false; + $component_db = um_db_get_component_db ($update->id_component_db); + $field = $component_db->field_name; + $values['db_field_value'] = $db_data->$field; + $values['id_component_db'] = $update->id_component_db; + $values['data'] = 'INSERT INTO `'.$component_db->table_name.'` (`'.implode('`,`', array_keys (get_object_vars ($db_data))).'`) VALUES (\''.implode('\',\'', get_object_vars ($db_data)).'\')'; + + break; + case 'db_schema': + $values['data'] = $update->data; + + break; + default: + return false; + } + $replace = array (); + for ($i = 0; $i < sizeof ($values); $i++) { + $replace[] = '?'; + } + $sql =& $db->prepare ('INSERT INTO tupdate ('.implode(',', array_keys ($values)).') VALUES ('.implode(',', $replace).')'); + $result =& $db->execute ($sql, array_values ($values)); + if (PEAR::isError ($result)) { + echo 'Error: '.$result->getMessage ().'
'; + return false; + } + return true; +} + +function um_get_update_types () { + $types = array (); + + $types['code'] = 'Code'; + $types['db_data'] = 'Database data'; + $types['db_schema'] = 'Database schema'; + $types['binary'] = 'Binary file'; + + return $types; +} + +function um_file_get_svn_revision ($file) { + return (int) exec ('svn info '.$file.'| grep "Revis" | head -1 | cut -f2 -d":"'); +} + +function um_file_uuencode ($file) { + $content = file_get_contents ($file); + return convert_uuencode ($content); +} +?> diff --git a/pandora_console/extensions/update_manager/lib/libupdate_manager_utils.php b/pandora_console/extensions/update_manager/lib/libupdate_manager_utils.php new file mode 100644 index 0000000000..a3836bc4e9 --- /dev/null +++ b/pandora_console/extensions/update_manager/lib/libupdate_manager_utils.php @@ -0,0 +1,62 @@ + diff --git a/pandora_console/extensions/update_manager/lib/load_updatemanager.php b/pandora_console/extensions/update_manager/lib/load_updatemanager.php new file mode 100644 index 0000000000..41494cb595 --- /dev/null +++ b/pandora_console/extensions/update_manager/lib/load_updatemanager.php @@ -0,0 +1,18 @@ + diff --git a/pandora_console/extensions/update_manager/load_updatemanager.php b/pandora_console/extensions/update_manager/load_updatemanager.php new file mode 100644 index 0000000000..1d3546be4a --- /dev/null +++ b/pandora_console/extensions/update_manager/load_updatemanager.php @@ -0,0 +1,17 @@ + diff --git a/pandora_console/extensions/update_manager/main.php b/pandora_console/extensions/update_manager/main.php new file mode 100644 index 0000000000..61ce0bd461 --- /dev/null +++ b/pandora_console/extensions/update_manager/main.php @@ -0,0 +1,97 @@ +'.__('Update manager').''; + +if (! file_exists ($settings->keygen_path)) { + echo '

'.__('Keygen file does not exists')."

"; + return; +} + +if (! is_executable ($settings->keygen_path)) { + echo '

'.__('Keygen is not executable')."

"; + return; +} + +$user_key = exec ($settings->keygen_path); + +$update_package = (bool) get_parameter_post ('update_package'); + +if ($update_package) { + echo 'Updating...'; + flush (); + $force = (bool) get_parameter_post ('force_update'); + um_client_upgrade_to_latest ($user_key, $force); + /* TODO: Meter una noticia en tnews*/ +} + +$settings = um_db_load_settings (); +$package = um_client_check_latest_update ($settings, $user_key); + +if (is_int ($package) && $package == 1) { + echo '
'.__('Your system is up-to-date').'.
'; +} elseif ($package === false) { + echo '
'.__('Server connection failed')."
"; +} elseif (is_int ($package) && $package == 0) { + echo '
'.__('Server authorization rejected')."
"; +} else { + echo '
'.__('There\'s a new update for Pandora')."
"; + + $table->width = '50%'; + $table->data = array (); + + $table->data[0][0] = ''.__('Id').''; + $table->data[0][1] = $package->id; + + $table->data[1][0] = ''.__('Timestamp').''; + $table->data[1][1] = $package->timestamp; + + $table->data[2][0] = ''.__('Description').''; + $table->data[2][1] = html_entity_decode ($package->description); + + print_table ($table); + echo '
'; + echo '
'; + echo __('Overwrite local changes'); + print_checkbox ('force_update', '1', false); + echo '

'; + print_input_hidden ('update_package', 1); + print_submit_button (__('Update'), 'update_button', false, 'class="sub upd"'); + echo '

'; + echo '
'; +} + +echo '

'.__('Your system version number is').': '.$settings->current_update.'

'; + +?> diff --git a/pandora_console/extensions/update_manager/settings.php b/pandora_console/extensions/update_manager/settings.php new file mode 100644 index 0000000000..3fa27e4c58 --- /dev/null +++ b/pandora_console/extensions/update_manager/settings.php @@ -0,0 +1,74 @@ + $value) { + um_db_update_setting ($key, $value); + } + echo "

".__('Update manager settings updated')."

"; +} + +$settings = um_db_load_settings (); + +echo '

'.__('Settings').'

'; +echo '
'; + +$table->width = '95%'; +$table->data = array (); + +$table->data[0][0] = ''.__('Customer key').''; +$table->data[0][1] = print_input_text ('keys[customer_key]', $settings->customer_key, '', 40, 255, true); + +$table->data[1][0] = ''.__('Update server host').''; +$table->data[1][1] = print_input_text ('keys[update_server_host]', $settings->update_server_host, '', 20, 255, true); + +$table->data[2][0] = ''.__('Update server path').''; +$table->data[2][1] = print_input_text ('keys[update_server_path]', $settings->update_server_path, '', 40, 255, true); + +$table->data[3][0] = ''.__('Update server port').''; +$table->data[3][1] = print_input_text ('keys[update_server_port]', $settings->update_server_port, '', 5, 5, true); + +$table->data[4][0] = ''.__('Binary input path').''; +$table->data[4][1] = print_input_text ('keys[updating_binary_path]', $settings->updating_binary_path, '', 40, 255, true); + +$table->data[5][0] = ''.__('Keygen path').''; +$table->data[5][1] = print_input_text ('keys[keygen_path]', $settings->keygen_path, '', 40, 255, true); + +print_table ($table); +echo '
'; +print_input_hidden ('update_settings', 1); +print_submit_button (__('Update'), 'update_button', false, 'class="sub upd"'); +echo '
'; +echo '
'; + +?> diff --git a/pandora_console/extensions/update_manager/sql/update_manager.sql b/pandora_console/extensions/update_manager/sql/update_manager.sql new file mode 100644 index 0000000000..57eb6f1588 --- /dev/null +++ b/pandora_console/extensions/update_manager/sql/update_manager.sql @@ -0,0 +1,5 @@ +CREATE TABLE `tupdate_settings` ( `key` varchar(255) default '', `value` varchar(255) default '', PRIMARY KEY (`key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO `tupdate_settings` VALUES ('current_update', '0'), ('customer_key', 'Insert your customer key here'), ('keygen_path', ''), ('update_server_host', ''), ('update_server_port', '80'), ('update_server_path', ''), ('updating_binary_path', 'Path where the updated binary files will be stored'), ('updating_code_path', 'Path where the updated code is stored'), ('dbname', ''), ('dbhost', ''), ('dbpass', ''), ('dbuser', ''); +CREATE TABLE `tupdate_package` ( id int(11) unsigned NOT NULL auto_increment, timestamp datetime NOT NULL, description mediumtext NOT NULL default '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `tupdate` ( id int(11) unsigned NOT NULL auto_increment, type enum('code', 'db_data', 'db_schema', 'binary'), id_update_package int(11) unsigned NOT NULL default 0, filename varchar(250) default '', checksum varchar(250) default '', previous_checksum varchar(250) default '', svn_version int(4) unsigned NOT NULL default 0, data LONGTEXT default '', data_rollback LONGTEXT default '', description TEXT default '', db_table_name varchar(140) default '', db_field_name varchar(140) default '', db_field_value varchar(1024) default '', PRIMARY KEY (`id`), FOREIGN KEY (`id_update_package`) REFERENCES tupdate_package(`id`) ON UPDATE CASCADE ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `tupdate_journal` ( id int(11) unsigned NOT NULL auto_increment, id_update int(11) unsigned NOT NULL default 0, PRIMARY KEY (`id`), FOREIGN KEY (`id_update`) REFERENCES tupdate(`id`) ON UPDATE CASCADE ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;