diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php index 0271488b65a..58f6af55d60 100644 --- a/htdocs/admin/system/dolibarr.php +++ b/htdocs/admin/system/dolibarr.php @@ -327,6 +327,7 @@ $configfileparameters = array( 'dolibarr_main_db_character_set' => $langs->trans("DBStoringCharset"), 'dolibarr_main_db_collation' => $langs->trans("DBSortingCollation"), '?dolibarr_main_db_prefix' => $langs->trans("DatabasePrefix"), + 'dolibarr_main_db_readonly' => $langs->trans("ReadOnlyMode"), 'separator2' => '', 'dolibarr_main_authentication' => $langs->trans("AuthenticationMode"), '?multicompany_transverse_mode'=> $langs->trans("MultiCompanyMode"), @@ -449,6 +450,13 @@ foreach ($configfileparameters as $key => $value) { if (!empty($valuetoshow)) { print img_warning($langs->trans('SwitchThisForABetterSecurity', 0)); } + } elseif ($newkey == 'dolibarr_main_db_readonly') { + print ${$newkey}; + + $valuetoshow = ${$newkey}; + if (!empty($valuetoshow)) { + print img_warning($langs->trans('ReadOnlyMode', 1)); + } } else { print (empty(${$newkey}) ? '' : ${$newkey}); } diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example index fba3e1004f4..71f0a82e32f 100644 --- a/htdocs/conf/conf.php.example +++ b/htdocs/conf/conf.php.example @@ -151,6 +151,15 @@ $dolibarr_main_db_character_set='utf8'; $dolibarr_main_db_collation='utf8_unicode_ci'; +// dolibarr_main_db_readonly +// Set this to 1 to have the application working in readonly mode. All sql access INSERT/UPDATE/DELETE/CREATE/ALTER/TRUNCATE/DROP will be disabled. +// Default value: 0 +// Examples: +// $dolibarr_main_db_readonly='0'; +// +$dolibarr_main_db_readonly=0; + + // dolibarr_main_instance_unique_id // An secret ID that is unique for each installation. // This value is also visible and never propagated outside of Dolibarr, so it can be used as a salt / key for some encryption. diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 343f4c8cc3e..541b1728753 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -266,7 +266,7 @@ class DoliDBMysqli extends DoliDB */ public function query($query, $usesavepoint = 0, $type = 'auto') { - global $conf; + global $conf, $dolibarr_main_db_readonly; $query = trim($query); @@ -278,6 +278,15 @@ class DoliDBMysqli extends DoliDB return false; // Return false = error if empty request } + if (!empty($dolibarr_main_db_readonly)) { + if (preg_match('/^(INSERT|UPDATE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) { + $this->lasterror = 'Application in read-only mode'; + $this->lasterrno = 'APPREADONLY'; + $this->lastquery = $query; + return false; + } + } + if (!$this->database_name) { // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE) $ret = $this->db->query($query); diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 5a9d47dc40c..866ae2edc88 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -498,7 +498,7 @@ class DoliDBPgsql extends DoliDB */ public function query($query, $usesavepoint = 0, $type = 'auto') { - global $conf; + global $conf, $dolibarr_main_db_readonly; $query = trim($query); @@ -527,6 +527,18 @@ class DoliDBPgsql extends DoliDB $SYSLOG_SQL_LIMIT = 10000; // limit log to 10kb per line to limit DOS attacks dol_syslog('sql='.substr($query, 0, $SYSLOG_SQL_LIMIT), LOG_DEBUG); } + if (empty($query)) { + return false; // Return false = error if empty request + } + + if (!empty($dolibarr_main_db_readonly)) { + if (preg_match('/^(INSERT|UPDATE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) { + $this->lasterror = 'Application in read-only mode'; + $this->lasterrno = 'APPREADONLY'; + $this->lastquery = $query; + return false; + } + } $ret = @pg_query($this->db, $query); diff --git a/htdocs/core/db/sqlite3.class.php b/htdocs/core/db/sqlite3.class.php index 563ccb19aac..9315320bf79 100644 --- a/htdocs/core/db/sqlite3.class.php +++ b/htdocs/core/db/sqlite3.class.php @@ -397,7 +397,7 @@ class DoliDBSqlite3 extends DoliDB */ public function query($query, $usesavepoint = 0, $type = 'auto') { - global $conf; + global $conf, $dolibarr_main_db_readonly; $ret = null; @@ -455,6 +455,15 @@ class DoliDBSqlite3 extends DoliDB return false; // Return false = error if empty request } + if (!empty($dolibarr_main_db_readonly)) { + if (preg_match('/^(INSERT|UPDATE|DELETE|CREATE|ALTER|TRUNCATE|DROP)/i', $query)) { + $this->lasterror = 'Application in read-only mode'; + $this->lasterrno = 'APPREADONLY'; + $this->lastquery = $query; + return false; + } + } + // Ordre SQL ne necessitant pas de connexion a une base (exemple: CREATE DATABASE) try { //$ret = $this->db->exec($query); diff --git a/scripts/accountancy/export-thirdpartyaccount.php b/scripts/accountancy/export-thirdpartyaccount.php index 6df1f5ca4b8..46dd481566d 100755 --- a/scripts/accountancy/export-thirdpartyaccount.php +++ b/scripts/accountancy/export-thirdpartyaccount.php @@ -96,9 +96,12 @@ if (empty($date_start) || empty($date_end)) { // We define date_start and date_e $date_start = dol_get_first_day($year_start, 10, false); $date_end = dol_get_last_day($year_start, 12, false); } -} else { } +/* + * Main + */ + llxHeader(); $form = new Form($db); @@ -186,9 +189,6 @@ if ($resql) { $i++; } - /* - * View - */ $thirdpartystatic = new Societe($db); diff --git a/scripts/company/sync_contacts_dolibarr2ldap.php b/scripts/company/sync_contacts_dolibarr2ldap.php index 53ec46ddcd8..e161a813ec7 100755 --- a/scripts/company/sync_contacts_dolibarr2ldap.php +++ b/scripts/company/sync_contacts_dolibarr2ldap.php @@ -69,6 +69,11 @@ foreach ($argv as $key => $val) { $now = $argv[1]; +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + print "Mails sending disabled (useless in batch mode)\n"; $conf->global->MAIN_DISABLE_ALL_MAILS = 1; // On bloque les mails print "\n"; diff --git a/scripts/cron/cron_run_jobs.php b/scripts/cron/cron_run_jobs.php index 80f586a6788..a4e015745ca 100755 --- a/scripts/cron/cron_run_jobs.php +++ b/scripts/cron/cron_run_jobs.php @@ -108,6 +108,11 @@ if ($key != $conf->global->CRON_KEY) { exit(-1); } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-only mode\n"; + exit(-1); +} + // If param userlogin is reserved word 'firstadmin' if ($userlogin == 'firstadmin') { $sql = 'SELECT login, entity from '.MAIN_DB_PREFIX.'user WHERE admin = 1 and statut = 1 ORDER BY entity LIMIT 1'; diff --git a/scripts/emailings/mailing-send.php b/scripts/emailings/mailing-send.php index 0d59a1b5db5..876895d7c87 100755 --- a/scripts/emailings/mailing-send.php +++ b/scripts/emailings/mailing-send.php @@ -86,6 +86,11 @@ if (!empty($conf->global->MAILING_DELAY)) { if ($conf->global->MAILING_LIMIT_SENDBYCLI == '-1') { } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-only mode\n"; + exit(-1); +} + $user = new User($db); // for signature, we use user send as parameter if (!empty($login)) { diff --git a/scripts/emailings/reset-invalid-emails.php b/scripts/emailings/reset-invalid-emails.php index 6eb31abe995..0e7fdb4e6bf 100755 --- a/scripts/emailings/reset-invalid-emails.php +++ b/scripts/emailings/reset-invalid-emails.php @@ -57,6 +57,7 @@ require_once DOL_DOCUMENT_ROOT."/comm/mailing/class/mailing.class.php"; $version = DOL_VERSION; $error = 0; + /* * Main */ @@ -71,6 +72,11 @@ if (!in_array($type, array('all', 'thirdparties', 'contacts', 'users', 'members' exit(-1); } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $db->begin(); diff --git a/scripts/invoices/email_unpaid_invoices_to_customers.php b/scripts/invoices/email_unpaid_invoices_to_customers.php index 41c84ee4d41..4657c16bd65 100755 --- a/scripts/invoices/email_unpaid_invoices_to_customers.php +++ b/scripts/invoices/email_unpaid_invoices_to_customers.php @@ -80,6 +80,11 @@ if ($mode != 'confirm') { $conf->global->MAIN_DISABLE_ALL_MAILS = 1; } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $sql = "SELECT f.ref, f.total_ttc, f.date_lim_reglement as due_date,"; $sql .= " s.rowid as sid, s.nom as name, s.email, s.default_lang"; if ($targettype == 'contacts') { diff --git a/scripts/invoices/email_unpaid_invoices_to_representatives.php b/scripts/invoices/email_unpaid_invoices_to_representatives.php index 3cc9ad1a0eb..606ac32ca66 100755 --- a/scripts/invoices/email_unpaid_invoices_to_representatives.php +++ b/scripts/invoices/email_unpaid_invoices_to_representatives.php @@ -76,6 +76,11 @@ if ($mode != 'confirm') { $conf->global->MAIN_DISABLE_ALL_MAILS = 1; } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $sql = "SELECT f.ref, f.total_ttc, f.date_lim_reglement as due_date, s.nom as name, s.email, s.default_lang,"; $sql .= " u.rowid as uid, u.lastname, u.firstname, u.email, u.lang"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; diff --git a/scripts/invoices/rebuild_merge_pdf.php b/scripts/invoices/rebuild_merge_pdf.php index 309de5fe4bd..b19398eda50 100755 --- a/scripts/invoices/rebuild_merge_pdf.php +++ b/scripts/invoices/rebuild_merge_pdf.php @@ -52,6 +52,7 @@ $langs->load("main"); $version = DOL_VERSION; $error = 0; + /* * Main */ @@ -66,6 +67,11 @@ if (!isset($argv[1])) { exit(-1); } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $diroutputpdf = $conf->facture->dir_output.'/temp'; $newlangid = 'en_EN'; // To force a new lang id $filter = array(); diff --git a/scripts/members/sync_members_dolibarr2ldap.php b/scripts/members/sync_members_dolibarr2ldap.php index 4ecbe2e9b08..66c245cf3eb 100755 --- a/scripts/members/sync_members_dolibarr2ldap.php +++ b/scripts/members/sync_members_dolibarr2ldap.php @@ -68,6 +68,11 @@ foreach ($argv as $key => $val) { } } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $now = $argv[1]; print "Mails sending disabled (useless in batch mode)\n"; diff --git a/scripts/members/sync_members_ldap2dolibarr.php b/scripts/members/sync_members_ldap2dolibarr.php index be312ec1932..b40a267d62e 100755 --- a/scripts/members/sync_members_ldap2dolibarr.php +++ b/scripts/members/sync_members_ldap2dolibarr.php @@ -146,6 +146,11 @@ if ($typeid <= 0) { exit(-2); } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + if (!$confirmed) { print "Hit Enter to continue or CTRL+C to stop...\n"; $input = trim(fgets(STDIN)); diff --git a/scripts/members/sync_members_types_dolibarr2ldap.php b/scripts/members/sync_members_types_dolibarr2ldap.php index cec998abda5..3d592673296 100755 --- a/scripts/members/sync_members_types_dolibarr2ldap.php +++ b/scripts/members/sync_members_types_dolibarr2ldap.php @@ -70,6 +70,12 @@ dol_syslog($script_file." launched with arg ".join(',', $argv)); * } */ +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + + $sql = "SELECT rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type"; diff --git a/scripts/members/sync_members_types_ldap2dolibarr.php b/scripts/members/sync_members_types_ldap2dolibarr.php index 9aea20fb209..12a83633725 100755 --- a/scripts/members/sync_members_types_ldap2dolibarr.php +++ b/scripts/members/sync_members_types_ldap2dolibarr.php @@ -88,6 +88,11 @@ foreach ($argv as $key => $val) { } } +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + print "Mails sending disabled (useless in batch mode)\n"; $conf->global->MAIN_DISABLE_ALL_MAILS = 1; // On bloque les mails print "\n"; diff --git a/scripts/website/migrate-news-joomla2dolibarr.php b/scripts/website/migrate-news-joomla2dolibarr.php index 605f982bd16..bb02274a6a3 100755 --- a/scripts/website/migrate-news-joomla2dolibarr.php +++ b/scripts/website/migrate-news-joomla2dolibarr.php @@ -63,8 +63,18 @@ include_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php'; include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/website2.lib.php'; + +/* + * Main + */ + $langs->load('main'); +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $joomlaserverinfoarray = preg_split('/(:|@|\/)/', $joomlaserverinfo); $joomlalogin = $joomlaserverinfoarray[0]; $joomlapass = $joomlaserverinfoarray[1]; diff --git a/scripts/website/regenerate-pages.php b/scripts/website/regenerate-pages.php index 46b9283a4cf..b37e17bf78a 100755 --- a/scripts/website/regenerate-pages.php +++ b/scripts/website/regenerate-pages.php @@ -58,8 +58,18 @@ include_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php'; include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/website2.lib.php'; + +/* + * Main + */ + $langs->load('main'); +if (!empty($dolibarr_main_db_readonly)) { + print "Error: instance in read-onyl mode\n"; + exit(-1); +} + $website = new Website($db); $result = $website->fetch(0, $websiteref); if ($result <= 0) {